LinuxÄÚºË Îĵµ·­Òë»ã×Ü ÏÂÔØ±¾ÎÄ

www.ourkernel.com ÎÒÃǵÄÄÚºË

DEVICE_ATTR(power,0644,show_power,store_power);

ÉϾäÉùÃ÷ÁËÒ»¸ö½Ð×ö\µÄÉ豸ÊôÐԽṹÌå. ´Ë½á ¹¹Ìå¿ÉÒÔÓÃÏÂÁнӿÚÌí¼Óµ½É豸»òͬÉ豸ɾ³ý:

´úÂë:

int device_create_file(struct device *device, struct device_attribute * entry); void device_remove_file(struct device * dev, struct device_attribute * attr); Àý:

´úÂë:

device_create_file(dev,&dev_attr_power); device_remove_file(dev,&dev_attr_power);

ÎļþÃûºÍģʽ½«·Ö±ðÊÇ\ºÍ0644(-rw-r--r--).

Devres

Ô­ÎÄ×÷ÕߣºTejun Heo ·­ ÒëÕߣºHenry deargodzw@gmail.com У ¶©Õߣº °æ±¾×´Ì¬£ºÒÑÍê³É

=====================================

Devres - É豸×ÊÔ´¹ÜÀí =====================

Tejun Heo

ÓÚ2007Äê1ÔÂ10ºÅµÚÒ»´ÎÆð²Ý

1.¼ò½é : ºÙ? Devres(É豸×ÊÔ´)?

2.Devres(É豸×ÊÔ´) : ¹û¿ÇÀïµÄDevres(É豸×ÊÔ´)

3.Devres(É豸×ÊÔ´)×é : ¾Û¼¯Devres(É豸×ÊÔ´)ºÍÊÍ·ÅDevres(É豸×ÊÔ´)

4.ÏêϸÄÚÈÝ : ÉúÃüÖÜÆÚ¹æÔò,µ÷ÓÃÉÏÏÂÎÄ, ...

5.·ÑÓà : ÎÒÃDZØÐëΪ´Ë¸¶³ö¶à´óµÄ´ú¼Û?

6.¹ÜÀí¼¶±ðµÄ½Ó¿ÚÁбí: ÏÖÓеÄÒѱ»ÊµÏֵĹÜÀí¼¶±ðµÄ½Ó¿Ú

17

www.ourkernel.com ÎÒÃǵÄÄÚºË

1.¼ò½é

------

µ±ÄãÕýÊÔ×ÅÓÃIOÓ³ÉäÀ´×ª»¯libata, devres(É豸×ÊÔ´)¾Í²úÉúÁË¡£Ã¿¸ö±»IOÓ³ÉäµÄµØÖ·¶¼Ó¦¸Ã±»±£´æÆðÀ´£¬¶øµ±Çý¶¯±»Ð¶ÔØÊ±¶¼Ó¦¸Ã±ä³ÉδӳÉäµÄ¡£¾Ù¸öÀý×ÓÀ´Ëµ£¬Ò»¸ö¼òµ¥µÄSFF ATA¿ØÖÆÆ÷(¾ÍÊÇÄÇÖֺܾ­µäµÄPCI IDE)ÔÚ±¾µØÄ£Ê½ÐèҪʹÓÃÎå¸öPCI BARS£¬²¢ÇÒËùÓеÄPCI BARS¶¼ÐèÒª±»Î¬»¤¡£

¾ÍºÍ´ó¶àÊýÆäËûµÄÉ豸Çý¶¯Ò»Ñù£¬ÔÚ->removeºÍ->probeʧ°Ü·¾¶Àïlibataµ×²ãÇý¶¯Ò²ÓкܶàµÄ©¶´¡£Êǵģ¬ÄÇÒ²ÐíÊÇÒòΪlibataµ×²ãÇý¶¯¿ª·¢ÕßÃǶ¼ÊÇһȺÀÁ¼Ò»ï£¬µ«ÊÇÊDz»ÊÇËùÓеĵײ㿪·¢Õß¶¼ÊÇÕâÑùÄØ£¿ÔÚûÓÐÈκιØÓÚBraindamagedµÄÎĵµµÄÇé¿öÏ£¬ÎÒ»¨ÁËÒ»ÌìµÄʱ¼äÀ´ÕÛÌÚBraindamagedÓ²¼þ£¬×îºóËü³É¹¦µÄ¹¤×÷ÁË¡£

³öÓÚijÖÖÔ­Òò£¬ÎÒÃDz¢Ã»ÓÐÏñ²âÊÔºËÐÄ´úÂëÒ»ÑùÀ´²âÊԵײãÇý¶¯£¬²¢ÇÒһЩÔÚÇý¶¯Ð¶ÔØÊ±·¢ÉúµÄ©¶´ÒÔ¼°Ò»Ð©³õʼ»¯Ê§°ÜҲûÄÜÒýÆðÎÒÃǵÄ×¢Òâ¡£¶ø¹ØÓÚ³õʼ»¯Ê§°ÜµÄ·¾¶ÔòÊǸü¼ÓÔã¸â£¬ÒòΪËüÐèÒªÓ¦¸¶¶à¸öÈë¿Úµã£¬¸ü²»ÓÃ˵ÍêÈ«±éÀúÁË¡£

ËùÒÔ£¬Ðí¶àµ×²ãÇý¶¯¶¼»áÔÚÐ¶ÔØÊ±²úÉú×ÊԴй¶£¬Ò»°ëµÄʧ°ÜÔ­Òò¶¼ÊÇÔÚʵÏÖprobe()ʱµ¼Öµģ¬µ±ËüÖ´ÐÐʧ°Üºó¾Í»á²úÉúй¶£¬Ò²Ðí»¹»á²úÉú¸ü¼ÓÒâÏë²»µ½µÄ´íÎó¡£IOÓ³ÉäÌí¼ÓÁ˸ü¶àÓëprobe()µÄ½áºÏ£¬µ±È»Ò²°üÀ¨msiºÍmsix¡£

2. Devres(É豸×ÊÔ´)

-------------------

É豸×ÊÔ´´Ó¸ù±¾ÉÏ˵¾ÍÊÇÒ»¸öÕ¼×ÅÄÚ´æµÄÓÉÉ豸½á¹¹ÌåÁ¬½Ó¶ø³ÉµÄÁ´±í¡£Ã¿¸öÉ豸×ÊÔ´Èë¿Ú¶¼ÓëÒ»¸öÊÍ·Å×ÊÔ´µÄº¯ÊýÏà¹ØÁª¡£Ò»¸öÉ豸×ÊÔ´ÄÜͨ¹ý¶àÖÖ·½Ê½À´ÊÍ·Å¡£²»¹ÜÊÇÄÇÒ»ÖÖ·½Ê½£¬ËùÓеÄÉ豸×ÊÔ´Èë¿Ú¶¼Ó¦¸ÃÔÚÇý¶¯±»Ð¶ÔØÊ±¶øÊͷŵô¡£ÊÍ·Å×ÊԴʱ£¬Ïà¹ØÁªµÄÊͷź¯Êý¾Í»á±»Ó¦Ó㬲¢ÇÒÉ豸×ÊÔ´Èë¿ÚÒ²»á±»Êͷŵô¡£

É豸Çý¶¯Ê¹ÓÃ×ÊԴʱ£¬¹ÜÀí¼¶±ð½Ó¿Ú¾Í»á±»´´½¨ÓÃÀ´Ê¹ÓÃÉ豸×ÊÔ´¡£¾ÙÀýÀ´Ëµ£¬Ê¹ÓÃdma_alloc_coherent()À´»ñµÃÁ¬ÐøµÄDMAÄÚ´æ¡£Õâ¸ö¹ÜÀí¼¶±ðµÄ°æ±¾±»³Æ×÷dmam_alloc_coherent()¡£ËüºÍdma_alloc_coherent()¹¦ÄÜ´óÖÂÒ»Ñù£¬³ýÁËDMAÄÚ´æ·ÖÅäʱʹÓÃËüÀ´¹ÜÀí£¬²¢ÇÒÔÚÐ¶ÔØÊ±×Ô¶¯ÊÍ·ÅËù·ÖÅäµÄÄڴ档ʵÏÖ¿´ÆðÀ´ºÍÏÂÃæÏàËÆ£º struct dma_devres{ size_t size; void *vaddr; dma_addr_t dma_handle; };

static void dmam_coherent_release(struct device *dev, void *res) {

struct dma_devres *this = res;

dma_free_coherent(dev, this->size, this->vaddr, this->dma_handle); }

18

www.ourkernel.com ÎÒÃǵÄÄÚºË

dmam_alloc_coherent(dev, size, dma_handle, gfp) { struct dma_devres *dr;

/* alloc DMA memory as usual */ vaddr = dma_alloc_coherent(...); ...

dr = devres_alloc(dmam_coherent_release, sizeof(*dr), gfp); ...

void *vaddr;

/* record size, vaddr, dma_handle in dr */ dr->vaddr = vaddr;

return vaddr;

}

Èç¹ûÒ»¸öÇý¶¯Ê¹ÓÃdmam_alloc_coherent(), ÄÇô±»·ÖÅäµÄÇøÓò¶¼»á±£Ö¤±»ÊͷŲ»¹ÜÊÇ·ñÊÇÖÐ;³õʼ»¯Ê§°Ü»¹ÊÇÇý¶¯±»Ð¶ÔØ¡£Èç¹û´ó¶àÊýµÄ×ÊÔ´¶¼ÊÇÓùÜÀí¼¶±ðµÄ½Ó¿ÚÀ´»ñµÃ£¬ÄÇôһ¸öÇý¶¯ÔÚ±àд³õʼ»¯ºÍÍ˳ö´úÂëʱ¾Í»áÏԵøü¼Ó¼òµ¥¡£³õʼ»¯Â·¾¶¿´ÆðÀ´´ó¸ÅºÍÏÂÃæºÜÏñ£º

my_init_one() { struct mydev *d;

...

devres_add(dev, dr);

d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL); if (!d) return -ENOMEM;

d->ring = dmam_alloc_coherent(...); if (!d->ring)

return -ENOMEM;

if (check something) ...

return register_to_upper_layer(d);

19

return -EINVAL;

www.ourkernel.com ÎÒÃǵÄÄÚºË

}

Í˳öʱ£º

my_remove_one() {

unregister_from_upper_layer(d); shutdown_my_hardware(); }

¾ÍÏñÉÏÃæÐ´µÄÄÇÑù£¬µ×²ãÇý¶¯ÔÚʹÓÃÉ豸×ÊÔ´µÄʱºò¸ü¼Ó¼òµ¥»¯¡£ÔÚά»¤µ×²ãÇý¶¯Ê±Ò²»á¸ü¼ÓÈÝÒס£µ±È»£¬µ±³õʼ»¯Ê§°Ü·¾¶±»Í˳ö·¾¶Ëù¹²Ïíʱ£¬Á½Õß¶¼ÐèÒª¸ü¶àµÄ²âÊÔ¡£

3. É豸×ÊÔ´×é -------------

É豸×ÊÔ´Èë¿Ú¿ÉÒÔÓÃÉ豸×ÊÔ´×éÀ´¼¯ÖÐÆðÀ´¡£µ±Ò»¸ö×é±»ÊÍ·Åʱ£¬ËùÓб»°üº¬µÄÉ豸×ÊÔ´Èë¿ÚÒÔ¼°±»Ç¶Ì×µÄ×é¶¼»á±»ÊÍ·Å¡£Ò»¸öϰ¹ßÊǵ±»ñÈ¡×ÊԴʧ°Üʱ¾Í»Ø¹öµ½Ö®Ç°µÄ״̬¡£¾ÙÀýÈçÏ£º

if (!devres_open_group(dev, NULL, GFP_KERNEL)) return -ENOMEM;

acquire A; if (failed) goto err;

acquire B; if (failed) goto err; ...

devres_remove_group(dev, NULL); return 0;

err:

devres_release_group(dev, NULL); return err_code;

ͨ³£µ±×ÊÔ´»ñȡʧ°Üʱ¾ÍÒâζ×Åprobeʧ°Ü£¬ÏñÉÏÃæµÄ¼Ü¹¹Í¨³£ÔÚÖмä²ãÇý¶¯£¨¾ÍÏñlibataºËÐIJ㣩ÉÏÊÇÊ®·ÖÓÐÓõģ¬ÕâÑùÒ²²»»áÔÚʧ°ÜʱÒýÆðËùνµÄ±ß¼ÊЧӦ¡£¶ÔÓÚLLDs£¬ÔÚ´ó¶àÊýÀý×ÓÖнö½öÊÇ·µ»Ø´íÎó´úÂë¾ÍÒѾ­×ã¹»ÁË¡£

20