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::{device_id::RawDeviceId, 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. 86 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. 95 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. 103 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. 126 #[inline] 127 pub fn is_link_up(&self) -> bool { 128 let phydev = self.0.get().cast_const(); 129 // SAFETY: By the type invariant of `Device`, `phydev` points to a valid 130 // `struct phy_device`, and there is no concurrent write to this field. 131 let link = unsafe { bindings::phy_device::link_raw(phydev) }; 132 link == 1 133 } 134 135 /// Gets the current auto-negotiation configuration. 136 /// 137 /// It returns true if auto-negotiation is enabled. 138 #[inline] 139 pub fn is_autoneg_enabled(&self) -> bool { 140 let phydev = self.0.get().cast_const(); 141 // SAFETY: By the type invariant of `Device`, `phydev` points to a valid 142 // `struct phy_device`, and there is no concurrent write to this field. 143 let autoneg = unsafe { bindings::phy_device::autoneg_raw(phydev) }; 144 autoneg == bindings::AUTONEG_ENABLE 145 } 146 147 /// Gets the current auto-negotiation state. 148 /// 149 /// It returns true if auto-negotiation is completed. 150 #[inline] 151 pub fn is_autoneg_completed(&self) -> bool { 152 let phydev = self.0.get().cast_const(); 153 // SAFETY: By the type invariant of `Device`, `phydev` points to a valid 154 // `struct phy_device`, and there is no concurrent write to this field. 155 let completed = unsafe { bindings::phy_device::autoneg_complete_raw(phydev) }; 156 completed == 1 157 } 158 159 /// Sets the speed of the PHY. 160 pub fn set_speed(&mut self, speed: u32) { 161 let phydev = self.0.get(); 162 // SAFETY: The struct invariant ensures that we may access 163 // this field without additional synchronization. 164 unsafe { (*phydev).speed = speed as c_int }; 165 } 166 167 /// Sets duplex mode. 168 pub fn set_duplex(&mut self, mode: DuplexMode) { 169 let phydev = self.0.get(); 170 let v = match mode { 171 DuplexMode::Full => bindings::DUPLEX_FULL, 172 DuplexMode::Half => bindings::DUPLEX_HALF, 173 DuplexMode::Unknown => bindings::DUPLEX_UNKNOWN, 174 }; 175 // SAFETY: The struct invariant ensures that we may access 176 // this field without additional synchronization. 177 unsafe { (*phydev).duplex = v as c_int }; 178 } 179 180 /// Reads a PHY register. 181 // This function reads a hardware register and updates the stats so takes `&mut self`. 182 pub fn read<R: reg::Register>(&mut self, reg: R) -> Result<u16> { 183 reg.read(self) 184 } 185 186 /// Writes a PHY register. 187 pub fn write<R: reg::Register>(&mut self, reg: R, val: u16) -> Result { 188 reg.write(self, val) 189 } 190 191 /// Reads a paged register. 192 pub fn read_paged(&mut self, page: u16, regnum: u16) -> Result<u16> { 193 let phydev = self.0.get(); 194 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 195 // So it's just an FFI call. 196 let ret = unsafe { bindings::phy_read_paged(phydev, page.into(), regnum.into()) }; 197 198 to_result(ret).map(|()| ret as u16) 199 } 200 201 /// Resolves the advertisements into PHY settings. 202 pub fn resolve_aneg_linkmode(&mut self) { 203 let phydev = self.0.get(); 204 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 205 // So it's just an FFI call. 206 unsafe { bindings::phy_resolve_aneg_linkmode(phydev) }; 207 } 208 209 /// Executes software reset the PHY via `BMCR_RESET` bit. 210 pub fn genphy_soft_reset(&mut self) -> Result { 211 let phydev = self.0.get(); 212 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 213 // So it's just an FFI call. 214 to_result(unsafe { bindings::genphy_soft_reset(phydev) }) 215 } 216 217 /// Initializes the PHY. 218 pub fn init_hw(&mut self) -> Result { 219 let phydev = self.0.get(); 220 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 221 // So it's just an FFI call. 222 to_result(unsafe { bindings::phy_init_hw(phydev) }) 223 } 224 225 /// Starts auto-negotiation. 226 pub fn start_aneg(&mut self) -> Result { 227 let phydev = self.0.get(); 228 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 229 // So it's just an FFI call. 230 to_result(unsafe { bindings::_phy_start_aneg(phydev) }) 231 } 232 233 /// Resumes the PHY via `BMCR_PDOWN` bit. 234 pub fn genphy_resume(&mut self) -> Result { 235 let phydev = self.0.get(); 236 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 237 // So it's just an FFI call. 238 to_result(unsafe { bindings::genphy_resume(phydev) }) 239 } 240 241 /// Suspends the PHY via `BMCR_PDOWN` bit. 242 pub fn genphy_suspend(&mut self) -> Result { 243 let phydev = self.0.get(); 244 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 245 // So it's just an FFI call. 246 to_result(unsafe { bindings::genphy_suspend(phydev) }) 247 } 248 249 /// Checks the link status and updates current link state. 250 pub fn genphy_read_status<R: reg::Register>(&mut self) -> Result<u16> { 251 R::read_status(self) 252 } 253 254 /// Updates the link status. 255 pub fn genphy_update_link(&mut self) -> Result { 256 let phydev = self.0.get(); 257 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 258 // So it's just an FFI call. 259 to_result(unsafe { bindings::genphy_update_link(phydev) }) 260 } 261 262 /// Reads link partner ability. 263 pub fn genphy_read_lpa(&mut self) -> Result { 264 let phydev = self.0.get(); 265 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 266 // So it's just an FFI call. 267 to_result(unsafe { bindings::genphy_read_lpa(phydev) }) 268 } 269 270 /// Reads PHY abilities. 271 pub fn genphy_read_abilities(&mut self) -> Result { 272 let phydev = self.0.get(); 273 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`. 274 // So it's just an FFI call. 275 to_result(unsafe { bindings::genphy_read_abilities(phydev) }) 276 } 277 } 278 279 impl AsRef<kernel::device::Device> for Device { 280 fn as_ref(&self) -> &kernel::device::Device { 281 let phydev = self.0.get(); 282 // SAFETY: The struct invariant ensures that `mdio.dev` is valid. 283 unsafe { kernel::device::Device::from_raw(addr_of_mut!((*phydev).mdio.dev)) } 284 } 285 } 286 287 /// Defines certain other features this PHY supports (like interrupts). 288 /// 289 /// These flag values are used in [`Driver::FLAGS`]. 290 pub mod flags { 291 /// PHY is internal. 292 pub const IS_INTERNAL: u32 = bindings::PHY_IS_INTERNAL; 293 /// PHY needs to be reset after the refclk is enabled. 294 pub const RST_AFTER_CLK_EN: u32 = bindings::PHY_RST_AFTER_CLK_EN; 295 /// Polling is used to detect PHY status changes. 296 pub const POLL_CABLE_TEST: u32 = bindings::PHY_POLL_CABLE_TEST; 297 /// Don't suspend. 298 pub const ALWAYS_CALL_SUSPEND: u32 = bindings::PHY_ALWAYS_CALL_SUSPEND; 299 } 300 301 /// An adapter for the registration of a PHY driver. 302 struct Adapter<T: Driver> { 303 _p: PhantomData<T>, 304 } 305 306 impl<T: Driver> Adapter<T> { 307 /// # Safety 308 /// 309 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 310 unsafe extern "C" fn soft_reset_callback(phydev: *mut bindings::phy_device) -> c_int { 311 from_result(|| { 312 // SAFETY: This callback is called only in contexts 313 // where we hold `phy_device->lock`, so the accessors on 314 // `Device` are okay to call. 315 let dev = unsafe { Device::from_raw(phydev) }; 316 T::soft_reset(dev)?; 317 Ok(0) 318 }) 319 } 320 321 /// # Safety 322 /// 323 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 324 unsafe extern "C" fn probe_callback(phydev: *mut bindings::phy_device) -> c_int { 325 from_result(|| { 326 // SAFETY: This callback is called only in contexts 327 // where we can exclusively access `phy_device` because 328 // it's not published yet, so the accessors on `Device` are okay 329 // to call. 330 let dev = unsafe { Device::from_raw(phydev) }; 331 T::probe(dev)?; 332 Ok(0) 333 }) 334 } 335 336 /// # Safety 337 /// 338 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 339 unsafe extern "C" fn get_features_callback(phydev: *mut bindings::phy_device) -> c_int { 340 from_result(|| { 341 // SAFETY: This callback is called only in contexts 342 // where we hold `phy_device->lock`, so the accessors on 343 // `Device` are okay to call. 344 let dev = unsafe { Device::from_raw(phydev) }; 345 T::get_features(dev)?; 346 Ok(0) 347 }) 348 } 349 350 /// # Safety 351 /// 352 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 353 unsafe extern "C" fn suspend_callback(phydev: *mut bindings::phy_device) -> c_int { 354 from_result(|| { 355 // SAFETY: The C core code ensures that the accessors on 356 // `Device` are okay to call even though `phy_device->lock` 357 // might not be held. 358 let dev = unsafe { Device::from_raw(phydev) }; 359 T::suspend(dev)?; 360 Ok(0) 361 }) 362 } 363 364 /// # Safety 365 /// 366 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 367 unsafe extern "C" fn resume_callback(phydev: *mut bindings::phy_device) -> c_int { 368 from_result(|| { 369 // SAFETY: The C core code ensures that the accessors on 370 // `Device` are okay to call even though `phy_device->lock` 371 // might not be held. 372 let dev = unsafe { Device::from_raw(phydev) }; 373 T::resume(dev)?; 374 Ok(0) 375 }) 376 } 377 378 /// # Safety 379 /// 380 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 381 unsafe extern "C" fn config_aneg_callback(phydev: *mut bindings::phy_device) -> c_int { 382 from_result(|| { 383 // SAFETY: This callback is called only in contexts 384 // where we hold `phy_device->lock`, so the accessors on 385 // `Device` are okay to call. 386 let dev = unsafe { Device::from_raw(phydev) }; 387 T::config_aneg(dev)?; 388 Ok(0) 389 }) 390 } 391 392 /// # Safety 393 /// 394 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 395 unsafe extern "C" fn read_status_callback(phydev: *mut bindings::phy_device) -> c_int { 396 from_result(|| { 397 // SAFETY: This callback is called only in contexts 398 // where we hold `phy_device->lock`, so the accessors on 399 // `Device` are okay to call. 400 let dev = unsafe { Device::from_raw(phydev) }; 401 T::read_status(dev)?; 402 Ok(0) 403 }) 404 } 405 406 /// # Safety 407 /// 408 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 409 unsafe extern "C" fn match_phy_device_callback( 410 phydev: *mut bindings::phy_device, 411 _phydrv: *const bindings::phy_driver, 412 ) -> c_int { 413 // SAFETY: This callback is called only in contexts 414 // where we hold `phy_device->lock`, so the accessors on 415 // `Device` are okay to call. 416 let dev = unsafe { Device::from_raw(phydev) }; 417 T::match_phy_device(dev).into() 418 } 419 420 /// # Safety 421 /// 422 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 423 unsafe extern "C" fn read_mmd_callback( 424 phydev: *mut bindings::phy_device, 425 devnum: i32, 426 regnum: u16, 427 ) -> i32 { 428 from_result(|| { 429 // SAFETY: This callback is called only in contexts 430 // where we hold `phy_device->lock`, so the accessors on 431 // `Device` are okay to call. 432 let dev = unsafe { Device::from_raw(phydev) }; 433 // CAST: the C side verifies devnum < 32. 434 let ret = T::read_mmd(dev, devnum as u8, regnum)?; 435 Ok(ret.into()) 436 }) 437 } 438 439 /// # Safety 440 /// 441 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 442 unsafe extern "C" fn write_mmd_callback( 443 phydev: *mut bindings::phy_device, 444 devnum: i32, 445 regnum: u16, 446 val: u16, 447 ) -> i32 { 448 from_result(|| { 449 // SAFETY: This callback is called only in contexts 450 // where we hold `phy_device->lock`, so the accessors on 451 // `Device` are okay to call. 452 let dev = unsafe { Device::from_raw(phydev) }; 453 T::write_mmd(dev, devnum as u8, regnum, val)?; 454 Ok(0) 455 }) 456 } 457 458 /// # Safety 459 /// 460 /// `phydev` must be passed by the corresponding callback in `phy_driver`. 461 unsafe extern "C" fn link_change_notify_callback(phydev: *mut bindings::phy_device) { 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::link_change_notify(dev); 467 } 468 } 469 470 /// Driver structure for a particular PHY type. 471 /// 472 /// Wraps the kernel's [`struct phy_driver`]. 473 /// This is used to register a driver for a particular PHY type with the kernel. 474 /// 475 /// # Invariants 476 /// 477 /// `self.0` is always in a valid state. 478 /// 479 /// [`struct phy_driver`]: srctree/include/linux/phy.h 480 #[repr(transparent)] 481 pub struct DriverVTable(Opaque<bindings::phy_driver>); 482 483 // SAFETY: `DriverVTable` doesn't expose any &self method to access internal data, so it's safe to 484 // share `&DriverVTable` across execution context boundaries. 485 unsafe impl Sync for DriverVTable {} 486 487 /// Creates a [`DriverVTable`] instance from [`Driver`]. 488 /// 489 /// This is used by [`module_phy_driver`] macro to create a static array of `phy_driver`. 490 /// 491 /// [`module_phy_driver`]: crate::module_phy_driver 492 pub const fn create_phy_driver<T: Driver>() -> DriverVTable { 493 // INVARIANT: All the fields of `struct phy_driver` are initialized properly. 494 DriverVTable(Opaque::new(bindings::phy_driver { 495 name: crate::str::as_char_ptr_in_const_context(T::NAME).cast_mut(), 496 flags: T::FLAGS, 497 phy_id: T::PHY_DEVICE_ID.id(), 498 phy_id_mask: T::PHY_DEVICE_ID.mask_as_int(), 499 soft_reset: if T::HAS_SOFT_RESET { 500 Some(Adapter::<T>::soft_reset_callback) 501 } else { 502 None 503 }, 504 probe: if T::HAS_PROBE { 505 Some(Adapter::<T>::probe_callback) 506 } else { 507 None 508 }, 509 get_features: if T::HAS_GET_FEATURES { 510 Some(Adapter::<T>::get_features_callback) 511 } else { 512 None 513 }, 514 match_phy_device: if T::HAS_MATCH_PHY_DEVICE { 515 Some(Adapter::<T>::match_phy_device_callback) 516 } else { 517 None 518 }, 519 suspend: if T::HAS_SUSPEND { 520 Some(Adapter::<T>::suspend_callback) 521 } else { 522 None 523 }, 524 resume: if T::HAS_RESUME { 525 Some(Adapter::<T>::resume_callback) 526 } else { 527 None 528 }, 529 config_aneg: if T::HAS_CONFIG_ANEG { 530 Some(Adapter::<T>::config_aneg_callback) 531 } else { 532 None 533 }, 534 read_status: if T::HAS_READ_STATUS { 535 Some(Adapter::<T>::read_status_callback) 536 } else { 537 None 538 }, 539 read_mmd: if T::HAS_READ_MMD { 540 Some(Adapter::<T>::read_mmd_callback) 541 } else { 542 None 543 }, 544 write_mmd: if T::HAS_WRITE_MMD { 545 Some(Adapter::<T>::write_mmd_callback) 546 } else { 547 None 548 }, 549 link_change_notify: if T::HAS_LINK_CHANGE_NOTIFY { 550 Some(Adapter::<T>::link_change_notify_callback) 551 } else { 552 None 553 }, 554 // SAFETY: The rest is zeroed out to initialize `struct phy_driver`, 555 // sets `Option<&F>` to be `None`. 556 ..unsafe { core::mem::MaybeUninit::<bindings::phy_driver>::zeroed().assume_init() } 557 })) 558 } 559 560 /// Driver implementation for a particular PHY type. 561 /// 562 /// This trait is used to create a [`DriverVTable`]. 563 #[vtable] 564 pub trait Driver { 565 /// Defines certain other features this PHY supports. 566 /// It is a combination of the flags in the [`flags`] module. 567 const FLAGS: u32 = 0; 568 569 /// The friendly name of this PHY type. 570 const NAME: &'static CStr; 571 572 /// This driver only works for PHYs with IDs which match this field. 573 /// The default id and mask are zero. 574 const PHY_DEVICE_ID: DeviceId = DeviceId::new_with_custom_mask(0, 0); 575 576 /// Issues a PHY software reset. 577 fn soft_reset(_dev: &mut Device) -> Result { 578 build_error!(VTABLE_DEFAULT_ERROR) 579 } 580 581 /// Sets up device-specific structures during discovery. 582 fn probe(_dev: &mut Device) -> Result { 583 build_error!(VTABLE_DEFAULT_ERROR) 584 } 585 586 /// Probes the hardware to determine what abilities it has. 587 fn get_features(_dev: &mut Device) -> Result { 588 build_error!(VTABLE_DEFAULT_ERROR) 589 } 590 591 /// Returns true if this is a suitable driver for the given phydev. 592 /// If not implemented, matching is based on [`Driver::PHY_DEVICE_ID`]. 593 fn match_phy_device(_dev: &Device) -> bool { 594 false 595 } 596 597 /// Configures the advertisement and resets auto-negotiation 598 /// if auto-negotiation is enabled. 599 fn config_aneg(_dev: &mut Device) -> Result { 600 build_error!(VTABLE_DEFAULT_ERROR) 601 } 602 603 /// Determines the negotiated speed and duplex. 604 fn read_status(_dev: &mut Device) -> Result<u16> { 605 build_error!(VTABLE_DEFAULT_ERROR) 606 } 607 608 /// Suspends the hardware, saving state if needed. 609 fn suspend(_dev: &mut Device) -> Result { 610 build_error!(VTABLE_DEFAULT_ERROR) 611 } 612 613 /// Resumes the hardware, restoring state if needed. 614 fn resume(_dev: &mut Device) -> Result { 615 build_error!(VTABLE_DEFAULT_ERROR) 616 } 617 618 /// Overrides the default MMD read function for reading a MMD register. 619 fn read_mmd(_dev: &mut Device, _devnum: u8, _regnum: u16) -> Result<u16> { 620 build_error!(VTABLE_DEFAULT_ERROR) 621 } 622 623 /// Overrides the default MMD write function for writing a MMD register. 624 fn write_mmd(_dev: &mut Device, _devnum: u8, _regnum: u16, _val: u16) -> Result { 625 build_error!(VTABLE_DEFAULT_ERROR) 626 } 627 628 /// Callback for notification of link change. 629 fn link_change_notify(_dev: &mut Device) {} 630 } 631 632 /// Registration structure for PHY drivers. 633 /// 634 /// Registers [`DriverVTable`] instances with the kernel. They will be unregistered when dropped. 635 /// 636 /// # Invariants 637 /// 638 /// The `drivers` slice are currently registered to the kernel via `phy_drivers_register`. 639 pub struct Registration { 640 drivers: Pin<&'static mut [DriverVTable]>, 641 } 642 643 // SAFETY: The only action allowed in a `Registration` instance is dropping it, which is safe to do 644 // from any thread because `phy_drivers_unregister` can be called from any thread context. 645 unsafe impl Send for Registration {} 646 647 impl Registration { 648 /// Registers a PHY driver. 649 pub fn register( 650 module: &'static crate::ThisModule, 651 drivers: Pin<&'static mut [DriverVTable]>, 652 ) -> Result<Self> { 653 if drivers.is_empty() { 654 return Err(code::EINVAL); 655 } 656 // SAFETY: The type invariants of [`DriverVTable`] ensure that all elements of 657 // the `drivers` slice are initialized properly. `drivers` will not be moved. 658 // So it's just an FFI call. 659 to_result(unsafe { 660 bindings::phy_drivers_register( 661 drivers[0].0.get(), 662 drivers.len().try_into()?, 663 module.as_ptr(), 664 ) 665 })?; 666 // INVARIANT: The `drivers` slice is successfully registered to the kernel via `phy_drivers_register`. 667 Ok(Registration { drivers }) 668 } 669 } 670 671 impl Drop for Registration { 672 fn drop(&mut self) { 673 // SAFETY: The type invariants guarantee that `self.drivers` is valid. 674 // So it's just an FFI call. 675 unsafe { 676 bindings::phy_drivers_unregister(self.drivers[0].0.get(), self.drivers.len() as i32) 677 }; 678 } 679 } 680 681 /// An identifier for PHY devices on an MDIO/MII bus. 682 /// 683 /// Represents the kernel's `struct mdio_device_id`. This is used to find an appropriate 684 /// PHY driver. 685 #[repr(transparent)] 686 #[derive(Clone, Copy)] 687 pub struct DeviceId(bindings::mdio_device_id); 688 689 impl DeviceId { 690 /// Creates a new instance with the exact match mask. 691 pub const fn new_with_exact_mask(id: u32) -> Self { 692 Self(bindings::mdio_device_id { 693 phy_id: id, 694 phy_id_mask: DeviceMask::Exact.as_int(), 695 }) 696 } 697 698 /// Creates a new instance with the model match mask. 699 pub const fn new_with_model_mask(id: u32) -> Self { 700 Self(bindings::mdio_device_id { 701 phy_id: id, 702 phy_id_mask: DeviceMask::Model.as_int(), 703 }) 704 } 705 706 /// Creates a new instance with the vendor match mask. 707 pub const fn new_with_vendor_mask(id: u32) -> Self { 708 Self(bindings::mdio_device_id { 709 phy_id: id, 710 phy_id_mask: DeviceMask::Vendor.as_int(), 711 }) 712 } 713 714 /// Creates a new instance with a custom match mask. 715 pub const fn new_with_custom_mask(id: u32, mask: u32) -> Self { 716 Self(bindings::mdio_device_id { 717 phy_id: id, 718 phy_id_mask: DeviceMask::Custom(mask).as_int(), 719 }) 720 } 721 722 /// Creates a new instance from [`Driver`]. 723 pub const fn new_with_driver<T: Driver>() -> Self { 724 T::PHY_DEVICE_ID 725 } 726 727 /// Get the MDIO device's PHY ID. 728 pub const fn id(&self) -> u32 { 729 self.0.phy_id 730 } 731 732 /// Get the MDIO device's match mask. 733 pub const fn mask_as_int(&self) -> u32 { 734 self.0.phy_id_mask 735 } 736 737 // macro use only 738 #[doc(hidden)] 739 pub const fn mdio_device_id(&self) -> bindings::mdio_device_id { 740 self.0 741 } 742 } 743 744 // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct mdio_device_id` 745 // and does not add additional invariants, so it's safe to transmute to `RawType`. 746 unsafe impl RawDeviceId for DeviceId { 747 type RawType = bindings::mdio_device_id; 748 } 749 750 enum DeviceMask { 751 Exact, 752 Model, 753 Vendor, 754 Custom(u32), 755 } 756 757 impl DeviceMask { 758 const MASK_EXACT: u32 = !0; 759 const MASK_MODEL: u32 = !0 << 4; 760 const MASK_VENDOR: u32 = !0 << 10; 761 762 const fn as_int(&self) -> u32 { 763 match self { 764 DeviceMask::Exact => Self::MASK_EXACT, 765 DeviceMask::Model => Self::MASK_MODEL, 766 DeviceMask::Vendor => Self::MASK_VENDOR, 767 DeviceMask::Custom(mask) => *mask, 768 } 769 } 770 } 771 772 /// Declares a kernel module for PHYs drivers. 773 /// 774 /// This creates a static array of kernel's `struct phy_driver` and registers it. 775 /// This also corresponds to the kernel's `MODULE_DEVICE_TABLE` macro, which embeds the information 776 /// for module loading into the module binary file. Every driver needs an entry in `device_table`. 777 /// 778 /// # Examples 779 /// 780 /// ``` 781 /// # mod module_phy_driver_sample { 782 /// use kernel::net::phy::{self, DeviceId}; 783 /// use kernel::prelude::*; 784 /// 785 /// kernel::module_phy_driver! { 786 /// drivers: [PhySample], 787 /// device_table: [ 788 /// DeviceId::new_with_driver::<PhySample>() 789 /// ], 790 /// name: "rust_sample_phy", 791 /// authors: ["Rust for Linux Contributors"], 792 /// description: "Rust sample PHYs driver", 793 /// license: "GPL", 794 /// } 795 /// 796 /// struct PhySample; 797 /// 798 /// #[vtable] 799 /// impl phy::Driver for PhySample { 800 /// const NAME: &'static CStr = c"PhySample"; 801 /// const PHY_DEVICE_ID: phy::DeviceId = phy::DeviceId::new_with_exact_mask(0x00000001); 802 /// } 803 /// # } 804 /// ``` 805 #[macro_export] 806 macro_rules! module_phy_driver { 807 (@replace_expr $_t:tt $sub:expr) => {$sub}; 808 809 (@count_devices $($x:expr),*) => { 810 0usize $(+ $crate::module_phy_driver!(@replace_expr $x 1usize))* 811 }; 812 813 (@device_table [$($dev:expr),+]) => { 814 $crate::module_device_table!( 815 "mdio", $crate::net::phy::DeviceId, 816 TABLE, @none, [$($dev),+] 817 ); 818 }; 819 820 (drivers: [$($driver:ident),+ $(,)?], device_table: [$($dev:expr),+ $(,)?], $($f:tt)*) => { 821 struct Module { 822 _reg: $crate::net::phy::Registration, 823 } 824 825 $crate::prelude::module! { 826 type: Module, 827 $($f)* 828 } 829 830 const _: () = { 831 static mut DRIVERS: [$crate::net::phy::DriverVTable; 832 $crate::module_phy_driver!(@count_devices $($driver),+)] = 833 [$($crate::net::phy::create_phy_driver::<$driver>()),+]; 834 835 impl $crate::Module for Module { 836 fn init(module: &'static $crate::ThisModule) -> Result<Self> { 837 // SAFETY: The anonymous constant guarantees that nobody else can access 838 // the `DRIVERS` static. The array is used only in the C side. 839 let drivers = unsafe { &mut DRIVERS }; 840 let mut reg = $crate::net::phy::Registration::register( 841 module, 842 ::core::pin::Pin::static_mut(drivers), 843 )?; 844 Ok(Module { _reg: reg }) 845 } 846 } 847 }; 848 849 $crate::module_phy_driver!(@device_table [$($dev),+]); 850 } 851 } 852