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