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