xref: /DragonOS/kernel/src/driver/base/device/dd.rs (revision 1ea2daad8121b77ed704e6d7c3a09f478147441d)
1 use core::intrinsics::unlikely;
2 
3 use alloc::{string::ToString, sync::Arc};
4 use intertrait::cast::CastArc;
5 use log::{debug, error, warn};
6 
7 use crate::{
8     driver::base::kobject::KObject,
9     filesystem::{
10         sysfs::{
11             file::sysfs_emit_str, sysfs_instance, Attribute, SysFSOpsSupport, SYSFS_ATTR_MODE_WO,
12         },
13         vfs::syscall::ModeType,
14     },
15     libs::wait_queue::WaitQueue,
16 };
17 use system_error::SystemError;
18 
19 use super::{
20     bus::BusNotifyEvent,
21     device_manager,
22     driver::{driver_manager, Driver, DriverManager},
23     Device, DeviceManager,
24 };
25 
26 static PROBE_WAIT_QUEUE: WaitQueue = WaitQueue::default();
27 
28 impl DeviceManager {
29     /// 尝试把一个设备与一个驱动匹配
30     ///
31     /// 当前函数会遍历整个bus的驱动列表,并且尝试把设备与每一个驱动进行匹配。
32     /// 一旦有一个驱动匹配成功,就会返回。
33     ///
34     /// ## 参数
35     ///
36     /// - `dev`: 设备
37     ///
38     /// ## 返回
39     ///
40     /// - Ok(true): 匹配成功
41     /// - Ok(false): 没有匹配成功
42     /// - Err(SystemError::ENODEV): 设备还没被注册
43     ///
44     /// ## 参考
45     ///
46     /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#1049
47     pub fn device_attach(&self, dev: &Arc<dyn Device>) -> Result<bool, SystemError> {
48         return self.do_device_attach(dev, false);
49     }
50 
51     pub fn device_initial_probe(&self, dev: &Arc<dyn Device>) -> Result<bool, SystemError> {
52         return self.do_device_attach(dev, true);
53     }
54 
55     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#978
56     fn do_device_attach(
57         &self,
58         dev: &Arc<dyn Device>,
59         allow_async: bool,
60     ) -> Result<bool, SystemError> {
61         if unlikely(allow_async) {
62             // todo!("do_device_attach: allow_async")
63             warn!("do_device_attach: allow_async is true, but currently not supported");
64         }
65         if dev.is_dead() {
66             return Ok(false);
67         }
68 
69         warn!("do_device_attach: dev: '{}'", dev.name());
70 
71         let mut do_async = false;
72         let mut r = Ok(false);
73 
74         if dev.driver().is_some() {
75             if self.device_is_bound(dev) {
76                 debug!(
77                     "do_device_attach: device '{}' is already bound.",
78                     dev.name()
79                 );
80                 return Ok(true);
81             }
82 
83             if self.device_bind_driver(dev).is_ok() {
84                 return Ok(true);
85             } else {
86                 dev.set_driver(None);
87                 return Ok(false);
88             }
89         } else {
90             debug!("do_device_attach: device '{}' is not bound.", dev.name());
91             let bus = dev
92                 .bus()
93                 .and_then(|bus| bus.upgrade())
94                 .ok_or(SystemError::EINVAL)?;
95             let mut data = DeviceAttachData::new(dev.clone(), allow_async, false);
96             let mut flag = false;
97             for driver in bus.subsystem().drivers().iter() {
98                 let r = self.do_device_attach_driver(driver, &mut data);
99                 if unlikely(r.is_err()) {
100                     flag = false;
101                     break;
102                 } else if r.unwrap() {
103                     flag = true;
104                     break;
105                 }
106             }
107 
108             if flag {
109                 r = Ok(true);
110             }
111 
112             if !flag && allow_async && data.have_async {
113                 // If we could not find appropriate driver
114                 // synchronously and we are allowed to do
115                 // async probes and there are drivers that
116                 // want to probe asynchronously, we'll
117                 // try them.
118 
119                 do_async = true;
120                 debug!(
121                     "do_device_attach: try scheduling asynchronous probe for device: {}",
122                     dev.name()
123                 );
124             }
125         }
126 
127         if do_async {
128             todo!("do_device_attach: do_async")
129         }
130         return r;
131     }
132 
133     /// 匹配设备和驱动
134     ///
135     /// ## 参数
136     ///
137     /// - `driver`: 驱动
138     /// - `data`: 匹配数据
139     ///
140     /// ## 返回
141     ///
142     /// - Ok(true): 匹配成功
143     /// - Ok(false): 没有匹配成功
144     /// - Err(SystemError): 匹配过程中出现意外错误,没有匹配成功
145     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#899
146     fn do_device_attach_driver(
147         &self,
148         driver: &Arc<dyn Driver>,
149         data: &mut DeviceAttachData,
150     ) -> Result<bool, SystemError> {
151         if let Some(bus) = driver.bus().and_then(|bus| bus.upgrade()) {
152             let r = bus.match_device(&data.dev, driver);
153 
154             if let Err(e) = r {
155                 // 如果不是ENOSYS,则总线出错
156                 if e != SystemError::ENOSYS {
157                     debug!(
158                         "do_device_attach_driver: bus.match_device() failed, dev: '{}', err: {:?}",
159                         data.dev.name(),
160                         e
161                     );
162                     return Err(e);
163                 }
164             } else if !r.unwrap() {
165                 return Ok(false);
166             }
167         }
168 
169         let async_allowed = driver.allows_async_probing();
170         if data.check_async && async_allowed != data.want_async {
171             return Ok(false);
172         }
173 
174         return driver_manager()
175             .probe_device(driver, &data.dev)
176             .map(|_| true);
177     }
178 
179     /// 检查设备是否绑定到驱动程序
180     ///
181     /// ## 参数
182     ///
183     /// - `dev`: 设备
184     ///
185     /// ## 返回
186     ///
187     /// 如果传递的设备已成功完成对驱动程序的探测,则返回true,否则返回false。
188     pub fn device_is_bound(&self, dev: &Arc<dyn Device>) -> bool {
189         return driver_manager().driver_is_bound(dev);
190     }
191 
192     /// 把一个驱动绑定到设备上
193     ///
194     /// 允许手动绑定驱动到设备上。调用者需要设置好dev.driver(),保证其不为None
195     ///
196     /// ## 参数
197     ///
198     /// - `dev`: 设备
199     ///
200     /// ## 建议
201     ///
202     /// 使用device_manager().driver_attach()会更好
203     ///
204     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#496
205     pub fn device_bind_driver(&self, dev: &Arc<dyn Device>) -> Result<(), SystemError> {
206         let r = driver_manager().driver_sysfs_add(dev);
207         if r.is_ok() {
208             self.device_links_force_bind(dev);
209             driver_manager().driver_bound(dev);
210         } else if let Some(bus) = dev.bus().and_then(|bus| bus.upgrade()) {
211             bus.subsystem().bus_notifier().call_chain(
212                 BusNotifyEvent::DriverNotBound,
213                 Some(dev),
214                 None,
215             );
216         }
217 
218         if let Err(e) = r.as_ref() {
219             error!(
220                 "device_bind_driver: driver_sysfs_add failed, dev: '{}', err: {:?}",
221                 dev.name(),
222                 e
223             );
224         }
225         return r;
226     }
227 
228     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#528
229     fn unbind_cleanup(&self, dev: &Arc<dyn Device>) {
230         dev.set_driver(None);
231         // todo: 添加更多操作,清理数据
232     }
233 }
234 
235 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#866
236 #[derive(Debug)]
237 #[allow(dead_code)]
238 struct DeviceAttachData {
239     dev: Arc<dyn Device>,
240 
241     ///  Indicates whether we are considering asynchronous probing or
242     ///  not. Only initial binding after device or driver registration
243     ///  (including deferral processing) may be done asynchronously, the
244     ///  rest is always synchronous, as we expect it is being done by
245     ///  request from userspace.
246     check_async: bool,
247 
248     /// Indicates if we are binding synchronous or asynchronous drivers.
249     /// When asynchronous probing is enabled we'll execute 2 passes
250     /// over drivers: first pass doing synchronous probing and second
251     /// doing asynchronous probing (if synchronous did not succeed -
252     /// most likely because there was no driver requiring synchronous
253     /// probing - and we found asynchronous driver during first pass).
254     /// The 2 passes are done because we can't shoot asynchronous
255     /// probe for given device and driver from bus_for_each_drv() since
256     /// driver pointer is not guaranteed to stay valid once
257     /// bus_for_each_drv() iterates to the next driver on the bus.
258     want_async: bool,
259 
260     /// We'll set have_async to 'true' if, while scanning for matching
261     /// driver, we'll encounter one that requests asynchronous probing.
262     have_async: bool,
263 }
264 
265 impl DeviceAttachData {
266     pub fn new(dev: Arc<dyn Device>, check_async: bool, want_async: bool) -> Self {
267         Self {
268             dev,
269             check_async,
270             want_async,
271             have_async: false,
272         }
273     }
274 
275     #[allow(dead_code)]
276     #[inline(always)]
277     fn set_have_async(&mut self) {
278         self.have_async = true;
279     }
280 }
281 
282 impl DriverManager {
283     /// 尝试把驱动绑定到现有的设备上
284     ///
285     /// 这个函数会遍历驱动现有的全部设备,然后尝试把他们匹配。
286     /// 一旦有一个设备匹配成功,就会返回,并且设备的driver字段会被设置。
287     pub fn driver_attach(&self, driver: &Arc<dyn Driver>) -> Result<(), SystemError> {
288         let bus = driver
289             .bus()
290             .and_then(|bus| bus.upgrade())
291             .ok_or(SystemError::EINVAL)?;
292         for dev in bus.subsystem().devices().iter() {
293             self.do_driver_attach(dev, driver);
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     #[inline(never)]
301     fn do_driver_attach(&self, device: &Arc<dyn Device>, driver: &Arc<dyn Driver>) -> bool {
302         let r = self.match_device(driver, device).unwrap_or(false);
303         if !r {
304             // 不匹配
305             return false;
306         }
307 
308         if driver.allows_async_probing() {
309             unimplemented!(
310                 "do_driver_attach: probe driver '{}' asynchronously",
311                 driver.name()
312             );
313         }
314 
315         if self.probe_device(driver, device).is_err() {
316             return false;
317         }
318 
319         return true;
320     }
321 
322     #[inline(always)]
323     pub fn match_device(
324         &self,
325         driver: &Arc<dyn Driver>,
326         device: &Arc<dyn Device>,
327     ) -> Result<bool, SystemError> {
328         return driver
329             .bus()
330             .and_then(|bus| bus.upgrade())
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().and_then(|bus| bus.upgrade()) {
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             error!(
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             error!(
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                 error!(
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                 error!(
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().and_then(|bus| bus.upgrade()) {
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             .and_then(|bus| bus.upgrade())
516             .ok_or(SystemError::EINVAL)?;
517         let r = bus.probe(device);
518         if r == Err(SystemError::ENOSYS) {
519             error!(
520                 "call_driver_probe: bus.probe() failed, dev: '{}', err: {:?}",
521                 device.name(),
522                 r
523             );
524             return r;
525         }
526 
527         if r.is_ok() {
528             return Ok(());
529         }
530 
531         let err = r.unwrap_err();
532         match err {
533             SystemError::ENODEV | SystemError::ENXIO => {
534                 debug!(
535                     "driver'{}': probe of {} rejects match {:?}",
536                     driver.name(),
537                     device.name(),
538                     err
539                 );
540             }
541 
542             _ => {
543                 warn!(
544                     "driver'{}': probe of {} failed with error {:?}",
545                     driver.name(),
546                     device.name(),
547                     err
548                 );
549             }
550         }
551 
552         return Err(err);
553     }
554 
555     /// 当设备被成功探测,进行了'设备->驱动'绑定后,调用这个函数,完成'驱动->设备'的绑定
556     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#393
557     fn driver_bound(&self, device: &Arc<dyn Device>) {
558         if self.driver_is_bound(device) {
559             warn!("driver_bound: device '{}' is already bound.", device.name());
560             return;
561         }
562 
563         let driver = device.driver().unwrap();
564         driver.add_device(device.clone());
565 
566         if let Some(bus) = device.bus().and_then(|bus| bus.upgrade()) {
567             bus.subsystem().bus_notifier().call_chain(
568                 BusNotifyEvent::BoundDriver,
569                 Some(device),
570                 None,
571             );
572         }
573 
574         // todo: 发送kobj bind的uevent
575     }
576 
577     fn driver_is_bound(&self, device: &Arc<dyn Device>) -> bool {
578         if let Some(driver) = device.driver() {
579             if driver.find_device_by_name(&device.name()).is_some() {
580                 return true;
581             }
582         }
583 
584         return false;
585     }
586 }
587 
588 /// 设备文件夹下的`dev`文件的属性
589 #[derive(Debug, Clone, Copy)]
590 pub struct DeviceAttrStateSynced;
591 
592 impl Attribute for DeviceAttrStateSynced {
593     fn mode(&self) -> ModeType {
594         // 0o444
595         return ModeType::S_IRUGO;
596     }
597 
598     fn name(&self) -> &str {
599         "state_synced"
600     }
601 
602     fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
603         let dev = kobj.cast::<dyn Device>().map_err(|kobj| {
604             error!(
605                 "Intertrait casting not implemented for kobj: {}",
606                 kobj.name()
607             );
608             SystemError::ENOSYS
609         })?;
610 
611         let val = dev.state_synced();
612         let val = if val { 1 } else { 0 };
613         return sysfs_emit_str(buf, format!("{}\n", val).as_str());
614     }
615 
616     fn support(&self) -> SysFSOpsSupport {
617         SysFSOpsSupport::ATTR_SHOW
618     }
619 }
620 
621 #[derive(Debug)]
622 pub(super) struct DeviceAttrCoredump;
623 
624 impl Attribute for DeviceAttrCoredump {
625     fn name(&self) -> &str {
626         "coredump"
627     }
628 
629     fn mode(&self) -> ModeType {
630         SYSFS_ATTR_MODE_WO
631     }
632 
633     fn support(&self) -> SysFSOpsSupport {
634         SysFSOpsSupport::ATTR_STORE
635     }
636 
637     fn store(&self, kobj: Arc<dyn KObject>, buf: &[u8]) -> Result<usize, SystemError> {
638         let dev = kobj.cast::<dyn Device>().map_err(|kobj| {
639             error!(
640                 "Intertrait casting not implemented for kobj: {}",
641                 kobj.name()
642             );
643             SystemError::ENOSYS
644         })?;
645 
646         let drv = dev.driver().ok_or(SystemError::EINVAL)?;
647         drv.coredump(&dev)?;
648 
649         return Ok(buf.len());
650     }
651 }
652