xref: /DragonOS/kernel/src/driver/base/device/dd.rs (revision 731bc2b32d7b37298883d7a15b6dca659b436ee4)
1 use core::intrinsics::unlikely;
2 
3 use alloc::{string::ToString, sync::Arc};
4 use intertrait::cast::CastArc;
5 
6 use crate::{
7     driver::base::kobject::KObject,
8     filesystem::{
9         sysfs::{
10             file::sysfs_emit_str, sysfs_instance, Attribute, SysFSOpsSupport, SYSFS_ATTR_MODE_WO,
11         },
12         vfs::syscall::ModeType,
13     },
14     libs::wait_queue::WaitQueue,
15 };
16 use system_error::SystemError;
17 
18 use super::{
19     bus::BusNotifyEvent,
20     device_manager,
21     driver::{driver_manager, Driver, DriverManager},
22     Device, DeviceManager,
23 };
24 
25 static PROBE_WAIT_QUEUE: WaitQueue = WaitQueue::default();
26 
27 impl DeviceManager {
28     /// 尝试把一个设备与一个驱动匹配
29     ///
30     /// 当前函数会遍历整个bus的驱动列表,并且尝试把设备与每一个驱动进行匹配。
31     /// 一旦有一个驱动匹配成功,就会返回。
32     ///
33     /// ## 参数
34     ///
35     /// - `dev`: 设备
36     ///
37     /// ## 返回
38     ///
39     /// - Ok(true): 匹配成功
40     /// - Ok(false): 没有匹配成功
41     /// - Err(SystemError::ENODEV): 设备还没被注册
42     ///
43     /// ## 参考
44     ///
45     /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#1049
46     pub fn device_attach(&self, dev: &Arc<dyn Device>) -> Result<bool, SystemError> {
47         return self.do_device_attach(dev, false);
48     }
49 
50     pub fn device_initial_probe(&self, dev: &Arc<dyn Device>) -> Result<bool, SystemError> {
51         return self.do_device_attach(dev, true);
52     }
53 
54     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#978
55     fn do_device_attach(
56         &self,
57         dev: &Arc<dyn Device>,
58         allow_async: bool,
59     ) -> Result<bool, SystemError> {
60         if unlikely(allow_async) {
61             // todo!("do_device_attach: allow_async")
62             kwarn!("do_device_attach: allow_async is true, but currently not supported");
63         }
64         if dev.is_dead() {
65             return Ok(false);
66         }
67 
68         kwarn!("do_device_attach: dev: '{}'", dev.name());
69 
70         let mut do_async = false;
71         let mut r = Ok(false);
72 
73         if dev.driver().is_some() {
74             if self.device_is_bound(dev) {
75                 kdebug!(
76                     "do_device_attach: device '{}' is already bound.",
77                     dev.name()
78                 );
79                 return Ok(true);
80             }
81 
82             if self.device_bind_driver(dev).is_ok() {
83                 return Ok(true);
84             } else {
85                 dev.set_driver(None);
86                 return Ok(false);
87             }
88         } else {
89             kdebug!("do_device_attach: device '{}' is not bound.", dev.name());
90             let bus = dev
91                 .bus()
92                 .and_then(|bus| bus.upgrade())
93                 .ok_or(SystemError::EINVAL)?;
94             let mut data = DeviceAttachData::new(dev.clone(), allow_async, false);
95             let mut flag = false;
96             for driver in bus.subsystem().drivers().iter() {
97                 let r = self.do_device_attach_driver(driver, &mut data);
98                 if unlikely(r.is_err()) {
99                     flag = false;
100                     break;
101                 } else if r.unwrap() {
102                     flag = true;
103                     break;
104                 }
105             }
106 
107             if flag {
108                 r = Ok(true);
109             }
110 
111             if !flag && allow_async && data.have_async {
112                 // If we could not find appropriate driver
113                 // synchronously and we are allowed to do
114                 // async probes and there are drivers that
115                 // want to probe asynchronously, we'll
116                 // try them.
117 
118                 do_async = true;
119                 kdebug!(
120                     "do_device_attach: try scheduling asynchronous probe for device: {}",
121                     dev.name()
122                 );
123             }
124         }
125 
126         if do_async {
127             todo!("do_device_attach: do_async")
128         }
129         return r;
130     }
131 
132     /// 匹配设备和驱动
133     ///
134     /// ## 参数
135     ///
136     /// - `driver`: 驱动
137     /// - `data`: 匹配数据
138     ///
139     /// ## 返回
140     ///
141     /// - Ok(true): 匹配成功
142     /// - Ok(false): 没有匹配成功
143     /// - Err(SystemError): 匹配过程中出现意外错误,没有匹配成功
144     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#899
145     fn do_device_attach_driver(
146         &self,
147         driver: &Arc<dyn Driver>,
148         data: &mut DeviceAttachData,
149     ) -> Result<bool, SystemError> {
150         if let Some(bus) = driver.bus().and_then(|bus| bus.upgrade()) {
151             let r = bus.match_device(&data.dev, driver);
152 
153             if let Err(e) = r {
154                 // 如果不是ENOSYS,则总线出错
155                 if e != SystemError::ENOSYS {
156                     kdebug!(
157                         "do_device_attach_driver: bus.match_device() failed, dev: '{}', err: {:?}",
158                         data.dev.name(),
159                         e
160                     );
161                     return Err(e);
162                 }
163             } else if !r.unwrap() {
164                 return Ok(false);
165             }
166         }
167 
168         let async_allowed = driver.allows_async_probing();
169         if data.check_async && async_allowed != data.want_async {
170             return Ok(false);
171         }
172 
173         return driver_manager()
174             .probe_device(driver, &data.dev)
175             .map(|_| true);
176     }
177 
178     /// 检查设备是否绑定到驱动程序
179     ///
180     /// ## 参数
181     ///
182     /// - `dev`: 设备
183     ///
184     /// ## 返回
185     ///
186     /// 如果传递的设备已成功完成对驱动程序的探测,则返回true,否则返回false。
187     pub fn device_is_bound(&self, dev: &Arc<dyn Device>) -> bool {
188         return driver_manager().driver_is_bound(dev);
189     }
190 
191     /// 把一个驱动绑定到设备上
192     ///
193     /// 允许手动绑定驱动到设备上。调用者需要设置好dev.driver(),保证其不为None
194     ///
195     /// ## 参数
196     ///
197     /// - `dev`: 设备
198     ///
199     /// ## 建议
200     ///
201     /// 使用device_manager().driver_attach()会更好
202     ///
203     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#496
204     pub fn device_bind_driver(&self, dev: &Arc<dyn Device>) -> Result<(), SystemError> {
205         let r = driver_manager().driver_sysfs_add(dev);
206         if r.is_ok() {
207             self.device_links_force_bind(dev);
208             driver_manager().driver_bound(dev);
209         } else if let Some(bus) = dev.bus().and_then(|bus| bus.upgrade()) {
210             bus.subsystem().bus_notifier().call_chain(
211                 BusNotifyEvent::DriverNotBound,
212                 Some(dev),
213                 None,
214             );
215         }
216 
217         if let Err(e) = r.as_ref() {
218             kerror!(
219                 "device_bind_driver: driver_sysfs_add failed, dev: '{}', err: {:?}",
220                 dev.name(),
221                 e
222             );
223         }
224         return r;
225     }
226 
227     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#528
228     fn unbind_cleanup(&self, dev: &Arc<dyn Device>) {
229         dev.set_driver(None);
230         // todo: 添加更多操作,清理数据
231     }
232 }
233 
234 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#866
235 #[derive(Debug)]
236 #[allow(dead_code)]
237 struct DeviceAttachData {
238     dev: Arc<dyn Device>,
239 
240     ///  Indicates whether we are considering asynchronous probing or
241     ///  not. Only initial binding after device or driver registration
242     ///  (including deferral processing) may be done asynchronously, the
243     ///  rest is always synchronous, as we expect it is being done by
244     ///  request from userspace.
245     check_async: bool,
246 
247     /// Indicates if we are binding synchronous or asynchronous drivers.
248     /// When asynchronous probing is enabled we'll execute 2 passes
249     /// over drivers: first pass doing synchronous probing and second
250     /// doing asynchronous probing (if synchronous did not succeed -
251     /// most likely because there was no driver requiring synchronous
252     /// probing - and we found asynchronous driver during first pass).
253     /// The 2 passes are done because we can't shoot asynchronous
254     /// probe for given device and driver from bus_for_each_drv() since
255     /// driver pointer is not guaranteed to stay valid once
256     /// bus_for_each_drv() iterates to the next driver on the bus.
257     want_async: bool,
258 
259     /// We'll set have_async to 'true' if, while scanning for matching
260     /// driver, we'll encounter one that requests asynchronous probing.
261     have_async: bool,
262 }
263 
264 impl DeviceAttachData {
265     pub fn new(dev: Arc<dyn Device>, check_async: bool, want_async: bool) -> Self {
266         Self {
267             dev,
268             check_async,
269             want_async,
270             have_async: false,
271         }
272     }
273 
274     #[allow(dead_code)]
275     #[inline(always)]
276     fn set_have_async(&mut self) {
277         self.have_async = true;
278     }
279 }
280 
281 impl DriverManager {
282     /// 尝试把驱动绑定到现有的设备上
283     ///
284     /// 这个函数会遍历驱动现有的全部设备,然后尝试把他们匹配。
285     /// 一旦有一个设备匹配成功,就会返回,并且设备的driver字段会被设置。
286     pub fn driver_attach(&self, driver: &Arc<dyn Driver>) -> Result<(), SystemError> {
287         let bus = driver
288             .bus()
289             .and_then(|bus| bus.upgrade())
290             .ok_or(SystemError::EINVAL)?;
291         for dev in bus.subsystem().devices().iter() {
292             self.do_driver_attach(dev, driver);
293         }
294 
295         return Ok(());
296     }
297 
298     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#1134
299     #[inline(never)]
300     fn do_driver_attach(&self, device: &Arc<dyn Device>, driver: &Arc<dyn Driver>) -> bool {
301         let r = self.match_device(driver, device).unwrap_or(false);
302         if !r {
303             // 不匹配
304             return false;
305         }
306 
307         if driver.allows_async_probing() {
308             unimplemented!(
309                 "do_driver_attach: probe driver '{}' asynchronously",
310                 driver.name()
311             );
312         }
313 
314         if self.probe_device(driver, device).is_err() {
315             return false;
316         }
317 
318         return true;
319     }
320 
321     #[inline(always)]
322     pub fn match_device(
323         &self,
324         driver: &Arc<dyn Driver>,
325         device: &Arc<dyn Device>,
326     ) -> Result<bool, SystemError> {
327         return driver
328             .bus()
329             .and_then(|bus| bus.upgrade())
330             .unwrap()
331             .match_device(device, driver);
332     }
333 
334     /// 尝试把设备和驱动绑定在一起
335     ///
336     ///
337     /// ## 返回
338     ///
339     /// - Ok(): 绑定成功
340     /// - Err(ENODEV): 设备未注册
341     /// - Err(EBUSY): 设备已经绑定到驱动上
342     ///
343     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#802
344     fn probe_device(
345         &self,
346         driver: &Arc<dyn Driver>,
347         device: &Arc<dyn Device>,
348     ) -> Result<(), SystemError> {
349         let r = self.do_probe_device(driver, device);
350         PROBE_WAIT_QUEUE.wakeup_all(None);
351         return r;
352     }
353 
354     fn do_probe_device(
355         &self,
356         driver: &Arc<dyn Driver>,
357         device: &Arc<dyn Device>,
358     ) -> Result<(), SystemError> {
359         if device.is_dead() || (!device.is_registered()) {
360             return Err(SystemError::ENODEV);
361         }
362         if device.driver().is_some() {
363             return Err(SystemError::EBUSY);
364         }
365 
366         device.set_can_match(true);
367 
368         self.really_probe(driver, device)?;
369 
370         return Ok(());
371     }
372 
373     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#584
374     fn really_probe(
375         &self,
376         driver: &Arc<dyn Driver>,
377         device: &Arc<dyn Device>,
378     ) -> Result<(), SystemError> {
379         let bind_failed = || {
380             device_manager().unbind_cleanup(device);
381         };
382 
383         let sysfs_failed = || {
384             if let Some(bus) = device.bus().and_then(|bus| bus.upgrade()) {
385                 bus.subsystem().bus_notifier().call_chain(
386                     BusNotifyEvent::DriverNotBound,
387                     Some(device),
388                     None,
389                 );
390             }
391         };
392 
393         let probe_failed = || {
394             self.remove_from_sysfs(device);
395         };
396 
397         let dev_groups_failed = || {
398             device_manager().remove(device);
399         };
400 
401         device.set_driver(Some(Arc::downgrade(driver)));
402 
403         self.add_to_sysfs(device).map_err(|e| {
404             kerror!(
405                 "really_probe: add_to_sysfs failed, dev: '{}', err: {:?}",
406                 device.name(),
407                 e
408             );
409             sysfs_failed();
410             bind_failed();
411             e
412         })?;
413 
414         self.call_driver_probe(device, driver).map_err(|e| {
415             kerror!(
416                 "really_probe: call_driver_probe failed, dev: '{}', err: {:?}",
417                 device.name(),
418                 e
419             );
420 
421             probe_failed();
422             sysfs_failed();
423             bind_failed();
424             e
425         })?;
426 
427         device_manager()
428             .add_groups(device, driver.dev_groups())
429             .map_err(|e| {
430                 kerror!(
431                     "really_probe: add_groups failed, dev: '{}', err: {:?}",
432                     device.name(),
433                     e
434                 );
435                 dev_groups_failed();
436                 probe_failed();
437                 sysfs_failed();
438                 bind_failed();
439                 e
440             })?;
441 
442         // 我们假设所有的设备都有 sync_state 这个属性。如果没有的话,也创建属性文件。
443         device_manager()
444             .create_file(device, &DeviceAttrStateSynced)
445             .map_err(|e| {
446                 kerror!(
447                     "really_probe: create_file failed, dev: '{}', err: {:?}",
448                     device.name(),
449                     e
450                 );
451                 dev_groups_failed();
452                 probe_failed();
453                 sysfs_failed();
454                 bind_failed();
455                 e
456             })?;
457 
458         self.driver_bound(device);
459 
460         return Ok(());
461     }
462 
463     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#434
464     fn add_to_sysfs(&self, device: &Arc<dyn Device>) -> Result<(), SystemError> {
465         let driver = device.driver().ok_or(SystemError::EINVAL)?;
466 
467         if let Some(bus) = device.bus().and_then(|bus| bus.upgrade()) {
468             bus.subsystem().bus_notifier().call_chain(
469                 BusNotifyEvent::BindDriver,
470                 Some(device),
471                 None,
472             );
473         }
474 
475         let driver_kobj = driver.clone() as Arc<dyn KObject>;
476         let device_kobj = device.clone() as Arc<dyn KObject>;
477 
478         sysfs_instance().create_link(Some(&driver_kobj), &device_kobj, device.name())?;
479 
480         let fail_rm_dev_link = || {
481             sysfs_instance().remove_link(&driver_kobj, device.name());
482         };
483 
484         sysfs_instance()
485             .create_link(Some(&device_kobj), &driver_kobj, "driver".to_string())
486             .map_err(|e| {
487                 fail_rm_dev_link();
488                 e
489             })?;
490 
491         device_manager()
492             .create_file(device, &DeviceAttrCoredump)
493             .map_err(|e| {
494                 sysfs_instance().remove_link(&device_kobj, "driver".to_string());
495                 fail_rm_dev_link();
496                 e
497             })?;
498 
499         return Ok(());
500     }
501 
502     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#469
503     fn remove_from_sysfs(&self, _device: &Arc<dyn Device>) {
504         todo!("remove_from_sysfs")
505     }
506 
507     fn call_driver_probe(
508         &self,
509         device: &Arc<dyn Device>,
510         driver: &Arc<dyn Driver>,
511     ) -> Result<(), SystemError> {
512         let bus = device
513             .bus()
514             .and_then(|bus| bus.upgrade())
515             .ok_or(SystemError::EINVAL)?;
516         let r = bus.probe(device);
517         if r == Err(SystemError::ENOSYS) {
518             kerror!(
519                 "call_driver_probe: bus.probe() failed, dev: '{}', err: {:?}",
520                 device.name(),
521                 r
522             );
523             return r;
524         }
525 
526         if r.is_ok() {
527             return Ok(());
528         }
529 
530         let err = r.unwrap_err();
531         match err {
532             SystemError::ENODEV | SystemError::ENXIO => {
533                 kdebug!(
534                     "driver'{}': probe of {} rejects match {:?}",
535                     driver.name(),
536                     device.name(),
537                     err
538                 );
539             }
540 
541             _ => {
542                 kwarn!(
543                     "driver'{}': probe of {} failed with error {:?}",
544                     driver.name(),
545                     device.name(),
546                     err
547                 );
548             }
549         }
550 
551         return Err(err);
552     }
553 
554     /// 当设备被成功探测,进行了'设备->驱动'绑定后,调用这个函数,完成'驱动->设备'的绑定
555     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#393
556     fn driver_bound(&self, device: &Arc<dyn Device>) {
557         if self.driver_is_bound(device) {
558             kwarn!("driver_bound: device '{}' is already bound.", device.name());
559             return;
560         }
561 
562         let driver = device.driver().unwrap();
563         driver.add_device(device.clone());
564 
565         if let Some(bus) = device.bus().and_then(|bus| bus.upgrade()) {
566             bus.subsystem().bus_notifier().call_chain(
567                 BusNotifyEvent::BoundDriver,
568                 Some(device),
569                 None,
570             );
571         }
572 
573         // todo: 发送kobj bind的uevent
574     }
575 
576     fn driver_is_bound(&self, device: &Arc<dyn Device>) -> bool {
577         if let Some(driver) = device.driver() {
578             if driver.find_device_by_name(&device.name()).is_some() {
579                 return true;
580             }
581         }
582 
583         return false;
584     }
585 }
586 
587 /// 设备文件夹下的`dev`文件的属性
588 #[derive(Debug, Clone, Copy)]
589 pub struct DeviceAttrStateSynced;
590 
591 impl Attribute for DeviceAttrStateSynced {
592     fn mode(&self) -> ModeType {
593         // 0o444
594         return ModeType::S_IRUGO;
595     }
596 
597     fn name(&self) -> &str {
598         "state_synced"
599     }
600 
601     fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
602         let dev = kobj.cast::<dyn Device>().map_err(|kobj| {
603             kerror!(
604                 "Intertrait casting not implemented for kobj: {}",
605                 kobj.name()
606             );
607             SystemError::ENOSYS
608         })?;
609 
610         let val = dev.state_synced();
611         let val = if val { 1 } else { 0 };
612         return sysfs_emit_str(buf, format!("{}\n", val).as_str());
613     }
614 
615     fn support(&self) -> SysFSOpsSupport {
616         SysFSOpsSupport::ATTR_SHOW
617     }
618 }
619 
620 #[derive(Debug)]
621 pub(super) struct DeviceAttrCoredump;
622 
623 impl Attribute for DeviceAttrCoredump {
624     fn name(&self) -> &str {
625         "coredump"
626     }
627 
628     fn mode(&self) -> ModeType {
629         SYSFS_ATTR_MODE_WO
630     }
631 
632     fn support(&self) -> SysFSOpsSupport {
633         SysFSOpsSupport::ATTR_STORE
634     }
635 
636     fn store(&self, kobj: Arc<dyn KObject>, buf: &[u8]) -> Result<usize, SystemError> {
637         let dev = kobj.cast::<dyn Device>().map_err(|kobj| {
638             kerror!(
639                 "Intertrait casting not implemented for kobj: {}",
640                 kobj.name()
641             );
642             SystemError::ENOSYS
643         })?;
644 
645         let drv = dev.driver().ok_or(SystemError::EINVAL)?;
646         drv.coredump(&dev)?;
647 
648         return Ok(buf.len());
649     }
650 }
651