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