~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/rust/kernel/net/phy.rs

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /rust/kernel/net/phy.rs (Version linux-6.12-rc7) and /rust/kernel/net/phy.rs (Version linux-6.3.13)


  1 // SPDX-License-Identifier: GPL-2.0               
  2                                                   
  3 // Copyright (C) 2023 FUJITA Tomonori <fujita.t    
  4                                                   
  5 //! Network PHY device.                           
  6 //!                                               
  7 //! C headers: [`include/linux/phy.h`](srctree    
  8                                                   
  9 use crate::{error::*, prelude::*, types::Opaqu    
 10 use core::{marker::PhantomData, ptr::addr_of_m    
 11                                                   
 12 pub mod reg;                                      
 13                                                   
 14 /// PHY state machine states.                     
 15 ///                                               
 16 /// Corresponds to the kernel's [`enum phy_sta    
 17 ///                                               
 18 /// Some of PHY drivers access to the state of    
 19 ///                                               
 20 /// [`enum phy_state`]: srctree/include/linux/    
 21 #[derive(PartialEq, Eq)]                          
 22 pub enum DeviceState {                            
 23     /// PHY device and driver are not ready fo    
 24     Down,                                         
 25     /// PHY is ready to send and receive packe    
 26     Ready,                                        
 27     /// PHY is up, but no polling or interrupt    
 28     Halted,                                       
 29     /// PHY is up, but is in an error state.      
 30     Error,                                        
 31     /// PHY and attached device are ready to d    
 32     Up,                                           
 33     /// PHY is currently running.                 
 34     Running,                                      
 35     /// PHY is up, but not currently plugged i    
 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 ha    
 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 ca    
 58 /// executes [`Driver`]'s methods during the c    
 59 ///                                               
 60 /// # Invariants                                  
 61 ///                                               
 62 /// - Referencing a `phy_device` using this st    
 63 ///   a context where all methods defined on t    
 64 /// - This struct always has a valid `self.0.m    
 65 ///                                               
 66 /// [`struct phy_device`]: srctree/include/lin    
 67 // During the calls to most functions in [`Dri    
 68 // unique for every instance of [`Device`]. `P    
 69 // [`Driver::resume`] and [`Driver::suspend`]:    
 70 // the lock held, thus guaranteeing that [`Dri    
 71 // [`Driver::resume`] and [`Driver::suspend`]     
 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    
 78     ///                                           
 79     /// # Safety                                  
 80     ///                                           
 81     /// For the duration of `'a`,                 
 82     /// - the pointer must point at a valid `p    
 83     ///   must be in a context where all metho    
 84     ///   are safe to call.                       
 85     /// - `(*ptr).mdio.dev` must be a valid.      
 86     unsafe fn from_raw<'a>(ptr: *mut bindings:    
 87         // CAST: `Self` is a `repr(transparent    
 88         let ptr = ptr.cast::<Self>();             
 89         // SAFETY: by the function requirement    
 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 ensure    
 98         // this field without additional synch    
 99         unsafe { (*phydev).phy_id }               
100     }                                             
101                                                   
102     /// Gets the state of PHY state machine st    
103     pub fn state(&self) -> DeviceState {          
104         let phydev = self.0.get();                
105         // SAFETY: The struct invariant ensure    
106         // this field without additional synch    
107         let state = unsafe { (*phydev).state }    
108         // TODO: this conversion code will be     
109         // when it becomes possible.              
110         match state {                             
111             bindings::phy_state_PHY_DOWN => De    
112             bindings::phy_state_PHY_READY => D    
113             bindings::phy_state_PHY_HALTED =>     
114             bindings::phy_state_PHY_ERROR => D    
115             bindings::phy_state_PHY_UP => Devi    
116             bindings::phy_state_PHY_RUNNING =>    
117             bindings::phy_state_PHY_NOLINK =>     
118             bindings::phy_state_PHY_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    
129         // generated code by bindgen when it b    
130         // SAFETY: The struct invariant ensure    
131         // this field without additional synch    
132         let bit_field = unsafe { &(*self.0.get    
133         bit_field.get(14, 1) == LINK_IS_UP        
134     }                                             
135                                                   
136     /// Gets the current auto-negotiation conf    
137     ///                                           
138     /// It returns true if auto-negotiation is    
139     pub fn is_autoneg_enabled(&self) -> bool {    
140         // TODO: the code to access to the bit    
141         // generated code by bindgen when it b    
142         // SAFETY: The struct invariant ensure    
143         // this field without additional synch    
144         let bit_field = unsafe { &(*self.0.get    
145         bit_field.get(13, 1) == bindings::AUTO    
146     }                                             
147                                                   
148     /// Gets the current auto-negotiation stat    
149     ///                                           
150     /// It returns true if auto-negotiation is    
151     pub fn is_autoneg_completed(&self) -> bool    
152         const AUTONEG_COMPLETED: u64 = 1;         
153         // TODO: the code to access to the bit    
154         // generated code by bindgen when it b    
155         // SAFETY: The struct invariant ensure    
156         // this field without additional synch    
157         let bit_field = unsafe { &(*self.0.get    
158         bit_field.get(15, 1) == AUTONEG_COMPLE    
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 ensure    
165         // this field without additional synch    
166         unsafe { (*phydev).speed = speed as i3    
167     }                                             
168                                                   
169     /// Sets duplex mode.                         
170     pub fn set_duplex(&mut self, mode: DuplexM    
171         let phydev = self.0.get();                
172         let v = match mode {                      
173             DuplexMode::Full => bindings::DUPL    
174             DuplexMode::Half => bindings::DUPL    
175             DuplexMode::Unknown => bindings::D    
176         };                                        
177         // SAFETY: The struct invariant ensure    
178         // this field without additional synch    
179         unsafe { (*phydev).duplex = v };          
180     }                                             
181                                                   
182     /// Reads a PHY register.                     
183     // This function reads a hardware register    
184     pub fn read<R: reg::Register>(&mut self, r    
185         reg.read(self)                            
186     }                                             
187                                                   
188     /// Writes a PHY register.                    
189     pub fn write<R: reg::Register>(&mut self,     
190         reg.write(self, val)                      
191     }                                             
192                                                   
193     /// Reads a paged register.                   
194     pub fn read_paged(&mut self, page: u16, re    
195         let phydev = self.0.get();                
196         // SAFETY: `phydev` is pointing to a v    
197         // So it's just an FFI call.              
198         let ret = unsafe { bindings::phy_read_    
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 s    
207     pub fn resolve_aneg_linkmode(&mut self) {     
208         let phydev = self.0.get();                
209         // SAFETY: `phydev` is pointing to a v    
210         // So it's just an FFI call.              
211         unsafe { bindings::phy_resolve_aneg_li    
212     }                                             
213                                                   
214     /// Executes software reset the PHY via `B    
215     pub fn genphy_soft_reset(&mut self) -> Res    
216         let phydev = self.0.get();                
217         // SAFETY: `phydev` is pointing to a v    
218         // So it's just an FFI call.              
219         to_result(unsafe { bindings::genphy_so    
220     }                                             
221                                                   
222     /// Initializes the PHY.                      
223     pub fn init_hw(&mut self) -> Result {         
224         let phydev = self.0.get();                
225         // SAFETY: `phydev` is pointing to a v    
226         // So it's just an FFI call.              
227         to_result(unsafe { bindings::phy_init_    
228     }                                             
229                                                   
230     /// Starts auto-negotiation.                  
231     pub fn start_aneg(&mut self) -> Result {      
232         let phydev = self.0.get();                
233         // SAFETY: `phydev` is pointing to a v    
234         // So it's just an FFI call.              
235         to_result(unsafe { bindings::_phy_star    
236     }                                             
237                                                   
238     /// Resumes the PHY via `BMCR_PDOWN` bit.     
239     pub fn genphy_resume(&mut self) -> Result     
240         let phydev = self.0.get();                
241         // SAFETY: `phydev` is pointing to a v    
242         // So it's just an FFI call.              
243         to_result(unsafe { bindings::genphy_re    
244     }                                             
245                                                   
246     /// Suspends the PHY via `BMCR_PDOWN` bit.    
247     pub fn genphy_suspend(&mut self) -> Result    
248         let phydev = self.0.get();                
249         // SAFETY: `phydev` is pointing to a v    
250         // So it's just an FFI call.              
251         to_result(unsafe { bindings::genphy_su    
252     }                                             
253                                                   
254     /// Checks the link status and updates cur    
255     pub fn genphy_read_status<R: reg::Register    
256         R::read_status(self)                      
257     }                                             
258                                                   
259     /// Updates the link status.                  
260     pub fn genphy_update_link(&mut self) -> Re    
261         let phydev = self.0.get();                
262         // SAFETY: `phydev` is pointing to a v    
263         // So it's just an FFI call.              
264         to_result(unsafe { bindings::genphy_up    
265     }                                             
266                                                   
267     /// Reads link partner ability.               
268     pub fn genphy_read_lpa(&mut self) -> Resul    
269         let phydev = self.0.get();                
270         // SAFETY: `phydev` is pointing to a v    
271         // So it's just an FFI call.              
272         to_result(unsafe { bindings::genphy_re    
273     }                                             
274                                                   
275     /// Reads PHY abilities.                      
276     pub fn genphy_read_abilities(&mut self) ->    
277         let phydev = self.0.get();                
278         // SAFETY: `phydev` is pointing to a v    
279         // So it's just an FFI call.              
280         to_result(unsafe { bindings::genphy_re    
281     }                                             
282 }                                                 
283                                                   
284 impl AsRef<kernel::device::Device> for Device     
285     fn as_ref(&self) -> &kernel::device::Devic    
286         let phydev = self.0.get();                
287         // SAFETY: The struct invariant ensure    
288         unsafe { kernel::device::Device::as_re    
289     }                                             
290 }                                                 
291                                                   
292 /// Defines certain other features this PHY su    
293 ///                                               
294 /// These flag values are used in [`Driver::FL    
295 pub mod flags {                                   
296     /// PHY is internal.                          
297     pub const IS_INTERNAL: u32 = bindings::PHY    
298     /// PHY needs to be reset after the refclk    
299     pub const RST_AFTER_CLK_EN: u32 = bindings    
300     /// Polling is used to detect PHY status c    
301     pub const POLL_CABLE_TEST: u32 = bindings:    
302     /// Don't suspend.                            
303     pub const ALWAYS_CALL_SUSPEND: u32 = bindi    
304 }                                                 
305                                                   
306 /// An adapter for the registration of a PHY d    
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 corresp    
315     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    
320             // where we hold `phy_device->lock    
321             // `Device` are okay to call.         
322             let dev = unsafe { Device::from_ra    
323             T::soft_reset(dev)?;                  
324             Ok(0)                                 
325         })                                        
326     }                                             
327                                                   
328     /// # Safety                                  
329     ///                                           
330     /// `phydev` must be passed by the corresp    
331     unsafe extern "C" fn probe_callback(phydev    
332         from_result(|| {                          
333             // SAFETY: This callback is called    
334             // where we can exclusively access    
335             // it's not published yet, so the     
336             // to call.                           
337             let dev = unsafe { Device::from_ra    
338             T::probe(dev)?;                       
339             Ok(0)                                 
340         })                                        
341     }                                             
342                                                   
343     /// # Safety                                  
344     ///                                           
345     /// `phydev` must be passed by the corresp    
346     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    
351             // where we hold `phy_device->lock    
352             // `Device` are okay to call.         
353             let dev = unsafe { Device::from_ra    
354             T::get_features(dev)?;                
355             Ok(0)                                 
356         })                                        
357     }                                             
358                                                   
359     /// # Safety                                  
360     ///                                           
361     /// `phydev` must be passed by the corresp    
362     unsafe extern "C" fn suspend_callback(phyd    
363         from_result(|| {                          
364             // SAFETY: The C core code ensures    
365             // `Device` are okay to call even     
366             // might not be held.                 
367             let dev = unsafe { Device::from_ra    
368             T::suspend(dev)?;                     
369             Ok(0)                                 
370         })                                        
371     }                                             
372                                                   
373     /// # Safety                                  
374     ///                                           
375     /// `phydev` must be passed by the corresp    
376     unsafe extern "C" fn resume_callback(phyde    
377         from_result(|| {                          
378             // SAFETY: The C core code ensures    
379             // `Device` are okay to call even     
380             // might not be held.                 
381             let dev = unsafe { Device::from_ra    
382             T::resume(dev)?;                      
383             Ok(0)                                 
384         })                                        
385     }                                             
386                                                   
387     /// # Safety                                  
388     ///                                           
389     /// `phydev` must be passed by the corresp    
390     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    
395             // where we hold `phy_device->lock    
396             // `Device` are okay to call.         
397             let dev = unsafe { Device::from_ra    
398             T::config_aneg(dev)?;                 
399             Ok(0)                                 
400         })                                        
401     }                                             
402                                                   
403     /// # Safety                                  
404     ///                                           
405     /// `phydev` must be passed by the corresp    
406     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    
411             // where we hold `phy_device->lock    
412             // `Device` are okay to call.         
413             let dev = unsafe { Device::from_ra    
414             T::read_status(dev)?;                 
415             Ok(0)                                 
416         })                                        
417     }                                             
418                                                   
419     /// # Safety                                  
420     ///                                           
421     /// `phydev` must be passed by the corresp    
422     unsafe extern "C" fn match_phy_device_call    
423         phydev: *mut bindings::phy_device,        
424     ) -> core::ffi::c_int {                       
425         // SAFETY: This callback is called onl    
426         // where we hold `phy_device->lock`, s    
427         // `Device` are okay to call.             
428         let dev = unsafe { Device::from_raw(ph    
429         T::match_phy_device(dev) as i32           
430     }                                             
431                                                   
432     /// # Safety                                  
433     ///                                           
434     /// `phydev` must be passed by the corresp    
435     unsafe extern "C" fn read_mmd_callback(       
436         phydev: *mut bindings::phy_device,        
437         devnum: i32,                              
438         regnum: u16,                              
439     ) -> i32 {                                    
440         from_result(|| {                          
441             // SAFETY: This callback is called    
442             // where we hold `phy_device->lock    
443             // `Device` are okay to call.         
444             let dev = unsafe { Device::from_ra    
445             // CAST: the C side verifies devnu    
446             let ret = T::read_mmd(dev, devnum     
447             Ok(ret.into())                        
448         })                                        
449     }                                             
450                                                   
451     /// # Safety                                  
452     ///                                           
453     /// `phydev` must be passed by the corresp    
454     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    
462             // where we hold `phy_device->lock    
463             // `Device` are okay to call.         
464             let dev = unsafe { Device::from_ra    
465             T::write_mmd(dev, devnum as u8, re    
466             Ok(0)                                 
467         })                                        
468     }                                             
469                                                   
470     /// # Safety                                  
471     ///                                           
472     /// `phydev` must be passed by the corresp    
473     unsafe extern "C" fn link_change_notify_ca    
474         // SAFETY: This callback is called onl    
475         // where we hold `phy_device->lock`, s    
476         // `Device` are okay to call.             
477         let dev = unsafe { Device::from_raw(ph    
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 pa    
486 ///                                               
487 /// # Invariants                                  
488 ///                                               
489 /// `self.0` is always in a valid state.          
490 ///                                               
491 /// [`struct phy_driver`]: srctree/include/lin    
492 #[repr(transparent)]                              
493 pub struct DriverVTable(Opaque<bindings::phy_d    
494                                                   
495 // SAFETY: `DriverVTable` doesn't expose any &    
496 // share `&DriverVTable` across execution cont    
497 unsafe impl Sync for DriverVTable {}              
498                                                   
499 /// Creates a [`DriverVTable`] instance from [    
500 ///                                               
501 /// This is used by [`module_phy_driver`] macr    
502 ///                                               
503 /// [`module_phy_driver`]: crate::module_phy_d    
504 pub const fn create_phy_driver<T: Driver>() ->    
505     // INVARIANT: All the fields of `struct ph    
506     DriverVTable(Opaque::new(bindings::phy_dri    
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_    
511         soft_reset: if T::HAS_SOFT_RESET {        
512             Some(Adapter::<T>::soft_reset_call    
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_ca    
523         } else {                                  
524             None                                  
525         },                                        
526         match_phy_device: if T::HAS_MATCH_PHY_    
527             Some(Adapter::<T>::match_phy_devic    
528         } else {                                  
529             None                                  
530         },                                        
531         suspend: if T::HAS_SUSPEND {              
532             Some(Adapter::<T>::suspend_callbac    
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_cal    
543         } else {                                  
544             None                                  
545         },                                        
546         read_status: if T::HAS_READ_STATUS {      
547             Some(Adapter::<T>::read_status_cal    
548         } else {                                  
549             None                                  
550         },                                        
551         read_mmd: if T::HAS_READ_MMD {            
552             Some(Adapter::<T>::read_mmd_callba    
553         } else {                                  
554             None                                  
555         },                                        
556         write_mmd: if T::HAS_WRITE_MMD {          
557             Some(Adapter::<T>::write_mmd_callb    
558         } else {                                  
559             None                                  
560         },                                        
561         link_change_notify: if T::HAS_LINK_CHA    
562             Some(Adapter::<T>::link_change_not    
563         } else {                                  
564             None                                  
565         },                                        
566         // SAFETY: The rest is zeroed out to i    
567         // sets `Option<&F>` to be `None`.        
568         ..unsafe { core::mem::MaybeUninit::<bi    
569     }))                                           
570 }                                                 
571                                                   
572 /// Driver implementation for a particular PHY    
573 ///                                               
574 /// This trait is used to create a [`DriverVTa    
575 #[vtable]                                         
576 pub trait Driver {                                
577     /// Defines certain other features this PH    
578     /// It is a combination of the flags in th    
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 I    
585     /// The default id and mask are zero.         
586     const PHY_DEVICE_ID: DeviceId = DeviceId::    
587                                                   
588     /// Issues a PHY software reset.              
589     fn soft_reset(_dev: &mut Device) -> Result    
590         kernel::build_error(VTABLE_DEFAULT_ERR    
591     }                                             
592                                                   
593     /// Sets up device-specific structures dur    
594     fn probe(_dev: &mut Device) -> Result {       
595         kernel::build_error(VTABLE_DEFAULT_ERR    
596     }                                             
597                                                   
598     /// Probes the hardware to determine what     
599     fn get_features(_dev: &mut Device) -> Resu    
600         kernel::build_error(VTABLE_DEFAULT_ERR    
601     }                                             
602                                                   
603     /// Returns true if this is a suitable dri    
604     /// If not implemented, matching is based     
605     fn match_phy_device(_dev: &Device) -> bool    
606         false                                     
607     }                                             
608                                                   
609     /// Configures the advertisement and reset    
610     /// if auto-negotiation is enabled.           
611     fn config_aneg(_dev: &mut Device) -> Resul    
612         kernel::build_error(VTABLE_DEFAULT_ERR    
613     }                                             
614                                                   
615     /// Determines the negotiated speed and du    
616     fn read_status(_dev: &mut Device) -> Resul    
617         kernel::build_error(VTABLE_DEFAULT_ERR    
618     }                                             
619                                                   
620     /// Suspends the hardware, saving state if    
621     fn suspend(_dev: &mut Device) -> Result {     
622         kernel::build_error(VTABLE_DEFAULT_ERR    
623     }                                             
624                                                   
625     /// Resumes the hardware, restoring state     
626     fn resume(_dev: &mut Device) -> Result {      
627         kernel::build_error(VTABLE_DEFAULT_ERR    
628     }                                             
629                                                   
630     /// Overrides the default MMD read functio    
631     fn read_mmd(_dev: &mut Device, _devnum: u8    
632         kernel::build_error(VTABLE_DEFAULT_ERR    
633     }                                             
634                                                   
635     /// Overrides the default MMD write functi    
636     fn write_mmd(_dev: &mut Device, _devnum: u    
637         kernel::build_error(VTABLE_DEFAULT_ERR    
638     }                                             
639                                                   
640     /// Callback for notification of link chan    
641     fn link_change_notify(_dev: &mut Device) {    
642 }                                                 
643                                                   
644 /// Registration structure for PHY drivers.       
645 ///                                               
646 /// Registers [`DriverVTable`] instances with     
647 ///                                               
648 /// # Invariants                                  
649 ///                                               
650 /// The `drivers` slice are currently register    
651 pub struct Registration {                         
652     drivers: Pin<&'static mut [DriverVTable]>,    
653 }                                                 
654                                                   
655 // SAFETY: The only action allowed in a `Regis    
656 // from any thread because `phy_drivers_unregi    
657 unsafe impl Send for Registration {}              
658                                                   
659 impl Registration {                               
660     /// Registers a PHY driver.                   
661     pub fn register(                              
662         module: &'static crate::ThisModule,       
663         drivers: Pin<&'static mut [DriverVTabl    
664     ) -> Result<Self> {                           
665         if drivers.is_empty() {                   
666             return Err(code::EINVAL);             
667         }                                         
668         // SAFETY: The type invariants of [`Dr    
669         // the `drivers` slice are initialized    
670         // So it's just an FFI call.              
671         to_result(unsafe {                        
672             bindings::phy_drivers_register(dri    
673         })?;                                      
674         // INVARIANT: The `drivers` slice is s    
675         Ok(Registration { drivers })              
676     }                                             
677 }                                                 
678                                                   
679 impl Drop for Registration {                      
680     fn drop(&mut self) {                          
681         // SAFETY: The type invariants guarant    
682         // So it's just an FFI call.              
683         unsafe {                                  
684             bindings::phy_drivers_unregister(s    
685         };                                        
686     }                                             
687 }                                                 
688                                                   
689 /// An identifier for PHY devices on an MDIO/M    
690 ///                                               
691 /// Represents the kernel's `struct mdio_devic    
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     
700     pub const fn new_with_exact_mask(id: u32)     
701         DeviceId {                                
702             id,                                   
703             mask: DeviceMask::Exact,              
704         }                                         
705     }                                             
706                                                   
707     /// Creates a new instance with the model     
708     pub const fn new_with_model_mask(id: u32)     
709         DeviceId {                                
710             id,                                   
711             mask: DeviceMask::Model,              
712         }                                         
713     }                                             
714                                                   
715     /// Creates a new instance with the vendor    
716     pub const fn new_with_vendor_mask(id: u32)    
717         DeviceId {                                
718             id,                                   
719             mask: DeviceMask::Vendor,             
720         }                                         
721     }                                             
722                                                   
723     /// Creates a new instance with a custom m    
724     pub const fn new_with_custom_mask(id: u32,    
725         DeviceId {                                
726             id,                                   
727             mask: DeviceMask::Custom(mask),       
728         }                                         
729     }                                             
730                                                   
731     /// Creates a new instance from [`Driver`]    
732     pub const fn new_with_driver<T: Driver>()     
733         T::PHY_DEVICE_ID                          
734     }                                             
735                                                   
736     /// Get a `mask` as u32.                      
737     pub const fn mask_as_int(&self) -> u32 {      
738         self.mask.as_int()                        
739     }                                             
740                                                   
741     // macro use only                             
742     #[doc(hidden)]                                
743     pub const fn mdio_device_id(&self) -> bind    
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                                                   
763     const fn as_int(&self) -> u32 {               
764         match self {                              
765             DeviceMask::Exact => Self::MASK_EX    
766             DeviceMask::Model => Self::MASK_MO    
767             DeviceMask::Vendor => Self::MASK_V    
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 `s    
776 /// This also corresponds to the kernel's `MOD    
777 /// for module loading into the module binary     
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::<PhySam    
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!("Ph    
803 ///     const PHY_DEVICE_ID: phy::DeviceId = p    
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!("Ph    
832 ///     const PHY_DEVICE_ID: phy::DeviceId = p    
833 /// }                                             
834 ///                                               
835 /// const _: () = {                               
836 ///     static mut DRIVERS: [::kernel::net::ph    
837 ///         [::kernel::net::phy::create_phy_dr    
838 ///                                               
839 ///     impl ::kernel::Module for Module {        
840 ///         fn init(module: &'static ThisModul    
841 ///             let drivers = unsafe { &mut DR    
842 ///             let mut reg = ::kernel::net::p    
843 ///                 module,                       
844 ///                 ::core::pin::Pin::static_m    
845 ///             )?;                               
846 ///             Ok(Module { _reg: reg })          
847 ///         }                                     
848 ///     }                                         
849 /// };                                            
850 ///                                               
851 /// #[cfg(MODULE)]                                
852 /// #[no_mangle]                                  
853 /// static __mod_mdio__phydev_device_table: [:    
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!(    
870     };                                            
871                                                   
872     (@device_table [$($dev:expr),+]) => {         
873         // SAFETY: C will not read off the end    
874         #[cfg(MODULE)]                            
875         #[no_mangle]                              
876         static __mod_mdio__phydev_device_table    
877             $crate::module_phy_driver!(@count_    
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),+ $(,)?], devi    
887         struct Module {                           
888             _reg: $crate::net::phy::Registrati    
889         }                                         
890                                                   
891         $crate::prelude::module! {                
892             type: Module,                         
893             $($f)*                                
894         }                                         
895                                                   
896         const _: () = {                           
897             static mut DRIVERS: [$crate::net::    
898                 $crate::module_phy_driver!(@co    
899                 [$($crate::net::phy::create_ph    
900                                                   
901             impl $crate::Module for Module {      
902                 fn init(module: &'static ThisM    
903                     // SAFETY: The anonymous c    
904                     // the `DRIVERS` static. T    
905                     let drivers = unsafe { &mu    
906                     let mut reg = $crate::net:    
907                         module,                   
908                         ::core::pin::Pin::stat    
909                     )?;                           
910                     Ok(Module { _reg: reg })      
911                 }                                 
912             }                                     
913         };                                        
914                                                   
915         $crate::module_phy_driver!(@device_tab    
916     }                                             
917 }                                                 
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php