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