sd卡驱动分析之card

http://m.blog.csdn.net/blog/rain0993/8476755

SD卡驱动分三层结构分别对应driver/mmc目录下的cardhostcore三个文件夹。其层次关系如下所示:

块设备驱动层(linux/block

内核空间file_operations调用

块设备请求处理(linux/driver/mmc/card

MMC核心层

linux/driver/mmc/core

mmc主机控制器mmc_host_ops

linux/driver/mmc/host

 

底层硬件(SD/MMC...

      分析过程分目录进行,为了与块设备层驱动接轨,这里我们以 自顶向下 的分析方法来处理 SD 卡的设备驱动。与块层联系最紧密的就是 card 目录,首先来看看与块设备接口的部分内容。

块请求处理(linux/driver/mmc/card

1.     probe

       按照惯例我们还是先来看下内核地图KconfigMakefile....

kconfig所给的信息来看我们最最关心的还是第7行和第17行,config MMC_BLOCKconfig MMC_BLOCK_BOUNCE。其中config MMC_BLOCK是整个MMC层工作的核心,对应于Makefile我们关注如下两行:

obj-$(CONFIG_MMC_BLOCK)          += mmc_block.o

mmc_block-objs                   := block.o queue.o

单凭直觉我们不难发现block.c是我们整个card目录的入口,打开文件不难发现在文件末尾处module_init(mmc_blk_init);将整个card目录入口描绘的淋漓尽致。还是来看看mmc_blk_init的相关内容。

[card/block.c]

673 static int __init mmc_blk_init(void)           

674 {           

675        int res;   

676               

677        res = register_blkdev(MMC_BLOCK_MAJOR, "mmc");   

678        if (res)   

679               goto out;

680               

681        res =mmc_register_driver(&mmc_driver); 

682        if (res)   

683               goto out2;

684               

685        return 0; 

686 out2:    

687        unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");

688 out:      

689        return res;

690 }    

667行开门见山,注册块设备驱动。相信看过LDD3的哥们都知道这个函数并无大用,他的作用也远没有他名字来的那般响亮。最多也就动态分配一个主设备号,然后在proc/device中留下点不为人知的记号,真正充NB的还是后面我们看到的add_disk

681行看似新鲜,不过看名字也就是往mmc core里注册点啥。他这一注册不打紧,关键是乱了我们的阵脚,说好了现在只说card目录的要是看了他就惹上core了,不看吧也就没法往下走了。干脆看一点点算了.....

[core/bus.c]

164 int mmc_register_driver(struct mmc_driver *drv)      

165 {    

166        drv->drv.bus = &mmc_bus_type;

167        return driver_register(&drv->drv);

168 }

166行和167知道一点点设备模型的哥们,估计在这里就要兴奋了。估计也就能猜到这个core大致都干了些啥勾当。不说别的166行的mmc_bus_type这条总线总得有人维护吧,自古以来这个又脏又累的活儿就是core干的,这里当然也不例外,不过这是后话。167行注册了个device_driver那当然也有个device了,至于他在哪我们留点神秘感以后再说。只知道有了driver_register自然会发生点啥,至少bus probe是肯定会调用的,下面就来看看这条总线究竟长啥样…

[core/bus.c]

139 static struct bus_type mmc_bus_type = {                   

140        .name             = "mmc",

141        .dev_attrs       = mmc_dev_attrs,  

142        .match            = mmc_bus_match,

143        .uevent           = mmc_bus_uevent,

144        .probe            = mmc_bus_probe,

145        .remove          = mmc_bus_remove,

146        .suspend  = mmc_bus_suspend,    

147        .resume          = mmc_bus_resume,

148 };

144probe之前先还是要match那么一下,match上了后面才会进一步去枚举。这里match方法和简单,直接返回1。全部调用probe,下面跟踪一下这个probe函数。

[core/bus.c]

99   static int mmc_bus_probe(struct device *dev)                   

100 {                  

101        struct mmc_driver *drv = to_mmc_driver(dev->driver);           

102        struct mmc_card *card = dev_to_mmc_card(dev);            

103                      

104        return drv->probe(card);             

105 }                  

101行和102行很明显mmc_driver内心都藏着一个设备模型的device_drivermmc_card怀里抱着一个设备模型的device,至于这两个结构到底长什么样,暂时还没有必要去研究,但是有一种预感mmc_card可能就是mmc_driver->driver命中注定的那个他了。

104行调用了mmc_driver中的probe方法,很显然这里就回朔到了card/block.c中刚刚注册的那个mmc_driver。原型如下:

[card/block.c]

663 static struct mmc_driver mmc_driver = {                  

664        .drv        = {

665               .name      = "mmcblk",

666        },          

667        .probe            = mmc_blk_probe,

668        .remove          = mmc_blk_remove,

669        .suspend  = mmc_blk_suspend,    

670        .resume          = mmc_blk_resume,

671 };

 

 

目光转向667行,mmc_blk_probe的实现如下:

[card/block.c]

584 static int mmc_blk_probe(struct mmc_card *card)                   

585 {                  

586        struct mmc_blk_data *md;          

587        int err;          

588                      

589        char cap_str[10];          

590                      

591        /*          

592        * Check that the card supports the command class(es) we need.             

593        */         

594        if (!(card->csd.cmdclass & CCC_BLOCK_READ))          

595               return -ENODEV; 

596                      

597        md = mmc_blk_alloc(card);        

598        if (IS_ERR(md))          

599               return PTR_ERR(md);  

600                      

601        err = mmc_blk_set_blksize(md, card);        

602        if (err)          

603               goto out;

604                      

605        string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2,         

606                      cap_str, sizeof(cap_str));

607        printk(KERN_INFO "%s: %s %s %s %s\n",             

608               md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),

609               cap_str, md->read_only ? "(ro)" : ""); 

610                      

611        mmc_set_drvdata(card, md);       

612        add_disk(md->disk);            

613        return 0;        

614                      

615 out:                    

616        mmc_blk_put(md);       

617                      

618        return err;             

619 }                  

586行定义一个struct mmc_blk_data指针变量,鉴于他的重要江湖地位还是先来了解一下这个结构。

[card/block.c]

57   struct mmc_blk_data {         

58          spinlock_t       lock;

59          struct gendisk  *disk;

60          struct mmc_queue queue;     

61                 

62          unsigned int    usage;

63          unsigned int    read_only;

64   };          

58行一个自旋锁,分配请求队列以及控制队列操作时会用到,姑且先说这些。

59行块设备层中大名鼎鼎的gendisk结构,表示一个磁盘设备,当然这里一张存储卡也就对应这么一个disk了。可见其显赫的江湖地位了.....

60行看名字就知道是包装过的请求队列,不管他隐藏的有多深,我们还是要来看个究竟.....

[card/queue.h]

7    struct mmc_queue {                           

8           struct mmc_card            *card;    

9           struct task_struct    *thread;         

10          struct semaphore    thread_sem;          

11          unsigned int           flags;     

12          struct request        *req;      

13          int                 (*issue_fn)(struct mmc_queue *, struct request *);

14          void               *data;

15          struct request_queue     *queue;         

16          struct scatterlist      *sg;       

17          char               *bounce_buf;

18          struct scatterlist      *bounce_sg;          

19          unsigned int           bounce_sg_len;     

20   };   

12行和15行是块设备那边要用到的结构也是这个mmc_queue的核心,至于其他的比如9task_struct指向应用进程scatterlist散列表等我们用到再说。回到mmc_blk_data

62-63行相当于一些个flags,标示一些卡的状态。

       好了,该看的都看到了,接下来就该回到mmc_blk_probe.....

597行分配mmc_blk_data,并进行相关的初始化。跟踪源码.....

[card/block.c]

472 static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)              

473 {                  

474        struct mmc_blk_data *md;          

475        int devidx, ret;             

476                      

477        devidx = find_first_zero_bit(dev_use, MMC_NUM_MINORS);       

478        if (devidx >= MMC_NUM_MINORS)        

479               return ERR_PTR(-ENOSPC);      

480        __set_bit(devidx, dev_use);         

481                      

482        md = kzalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);           

483        if (!md) {             

484               ret = -ENOMEM;  

485               goto out;

486        }           

487                      

488                      

489        /*          

490        * Set the read-only status based on the supported commands          

491        * and the write protect switch.          

492        */         

493        md->read_only = mmc_blk_readonly(card);       

494                      

495        md->disk = alloc_disk(1 << MMC_SHIFT);             

496        if (md->disk == NULL) {           

497               ret = -ENOMEM;  

498               goto err_kfree;      

499        }           

500                      

501        spin_lock_init(&md->lock);        

502        md->usage = 1;            

503                      

504        ret = mmc_init_queue(&md->queue, card, &md->lock);          

505        if (ret)           

506               goto err_putdisk;   

507                      

508        md->queue.issue_fn = mmc_blk_issue_rq;         

509        md->queue.data = md;         

510                      

511        md->disk->major   = MMC_BLOCK_MAJOR;  

512        md->disk->first_minor = devidx << MMC_SHIFT;          

513        md->disk->fops = &mmc_bdops;        

514        md->disk->private_data = md;            

515        md->disk->queue = md->queue.queue;       

516        md->disk->driverfs_dev = &card->dev;             

517                      

518        /*          

519        * As discussed on lkml, GENHD_FL_REMOVABLE should:         

520        *          

521        * - be set for removable media with permanent block devices         

522        * - be unset for removable block devices with permanent media            

523        *          

524        * Since MMC block devices clearly fall under the second        

525        * case, we do not set GENHD_FL_REMOVABLE.  Userspace             

526        * should use the block device creation/destruction hotplug             

527        * messages to tell when the card is present.       

528        */         

529                      

530        sprintf(md->disk->disk_name, "mmcblk%d", devidx);             

531                      

532        blk_queue_logical_block_size(md->queue.queue, 512);            

533                      

534        if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {             

535               /*   

536               * The EXT_CSD sector count is in number or 512 byte   

537               * sectors.     

538               */  

539               set_capacity(md->disk, card->ext_csd.sectors);   

540        } else {         

541               /*   

542               * The CSD capacity field is in units of read_blkbits. 

543               * set_capacity takes units of 512 bytes.     

544               */  

545               set_capacity(md->disk, 

546                      card->csd.capacity << (card->csd.read_blkbits - 9));

547        }           

548        return md;            

549                      

550 err_putdisk:               

551        put_disk(md->disk);            

552 err_kfree:                  

553        kfree(md);            

554 out:                    

555        return ERR_PTR(ret);          

556 }                  

代码虽然有点长但是还算是比较简单,我们分段来看....

477-480行是linux惯用的伎俩了,早在USB中我们就见到了,无非就是从dev_use这张“位图”中找出一个没用的,填充进去。

493行获取卡的只读状态,mmc_blk_readonly(card);会返回卡读到或设置的一些状态信息,很显然程序在这之前已经读取了卡的设备,具体在什么时候进行的后面再说。

495行分配一个disk结构了,可见这个disk支持的分区数最大是(1 << MMC_SHIFT)

504行我们再说块设备驱动开发的时候已经说的很明确了,对于一个设备来讲无论采用何种方式gendiskrequest这两个是肯定要存在的。这里调用mmc_init_queue来初始化request的相关内容。具体如下:

[card/queue.c]

111 int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock)  

112 {                                

113        struct mmc_host *host = card->host;                        

114        u64 limit = BLK_BOUNCE_HIGH;                         

115        int ret;                         

116                                    

117        if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)                       

118               limit = *mmc_dev(host)->dma_mask;               

119                                    

120        mq->card = card;                       

121        mq->queue =blk_init_queue(mmc_request, lock);                          

122        if (!mq->queue)                         

123               return -ENOMEM;              

124                                    

125        mq->queue->queuedata = mq;                          

126        mq->req = NULL;                      

127                                    

128        blk_queue_prep_rq(mq->queue, mmc_prep_request);                      

129        blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN, NULL);                       

130        queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue);                       

131                                    

132 #ifdef CONFIG_MMC_BLOCK_BOUNCE                            

133        if (host->max_hw_segs == 1) {                        

134               unsigned int bouncesz;                

135                                    

136               bouncesz = MMC_QUEUE_BOUNCESZ;                

137                                    

138               if (bouncesz > host->max_req_size)                  

139                      bouncesz = host->max_req_size;         

140               if (bouncesz > host->max_seg_size)                  

141                      bouncesz = host->max_seg_size;         

142               if (bouncesz > (host->max_blk_count * 512))                  

143                      bouncesz = host->max_blk_count * 512;            

144                                    

145               if (bouncesz > 512) {                  

146                      mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);          

147                      if (!mq->bounce_buf) {       

148                             printk(KERN_WARNING "%s: unable to " 

149                                    allocate bounce buffer\n,

150                                    mmc_card_name(card));

151                      }           

152               }                  

153                                    

154               if (mq->bounce_buf) {               

155                      blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY);         

156                      blk_queue_max_sectors(mq->queue, bouncesz / 512);       

157                      blk_queue_max_phys_segments(mq->queue, bouncesz / 512);          

158                      blk_queue_max_hw_segments(mq->queue, bouncesz / 512);            

159                      blk_queue_max_segment_size(mq->queue, bouncesz);             

160                                    

161                      mq->sg = kmalloc(sizeof(struct scatterlist),        

162                             GFP_KERNEL);   

163                      if (!mq->sg) {       

164                             ret = -ENOMEM;  

165                             goto cleanup_queue;     

166                      }           

167                      sg_init_table(mq->sg, 1);            

168                                    

169                      mq->bounce_sg = kmalloc(sizeof(struct scatterlist) *         

170                             bouncesz / 512, GFP_KERNEL); 

171                      if (!mq->bounce_sg) {         

172                             ret = -ENOMEM;  

173                             goto cleanup_queue;     

174                      }           

175                      sg_init_table(mq->bounce_sg, bouncesz / 512);         

176               }                  

177        }                         

178 #endif                                

179                                    

180        if (!mq->bounce_buf) {                     

181               blk_queue_bounce_limit(mq->queue, limit);                    

182               blk_queue_max_sectors(mq->queue,                 

183                      min(host->max_blk_count, host->max_req_size / 512));           

184               blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);              

185               blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);                  

186               blk_queue_max_segment_size(mq->queue, host->max_seg_size);                   

187                                    

188               mq->sg = kmalloc(sizeof(struct scatterlist) *                    

189                      host->max_phys_segs, GFP_KERNEL);            

190               if (!mq->sg) {              

191                      ret = -ENOMEM;         

192                      goto cleanup_queue;            

193               }                  

194               sg_init_table(mq->sg, host->max_phys_segs);                  

195        }                         

196                                    

197        init_MUTEX(&mq->thread_sem);                           

198                                    

199        mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd");                     

200        if (IS_ERR(mq->thread)) {                       

201               ret = PTR_ERR(mq->thread);                    

202               goto free_bounce_sg;                  

203        }                         

204                                    

205        return 0;                      

206 free_bounce_sg:                              

207      if (mq->bounce_sg)                           

208             kfree(mq->bounce_sg);               

209      mq->bounce_sg = NULL;                          

210 cleanup_queue:                                

211      if (mq->sg)                         

212               kfree(mq->sg);                    

213        mq->sg = NULL;                       

214        if (mq->bounce_buf)                         

215               kfree(mq->bounce_buf);                    

216        mq->bounce_buf = NULL;                        

217        blk_cleanup_queue(mq->queue);                       

218        return ret;                           

219 }    

又是一段冗长的代码,没办法既然linux说这事得说来话长那么我们也只能长话长说了。前面看过了struct mmc_queue结构,这里就不再重复了,来点实在的......

121行赫赫有名的blk_init_queue就赤裸裸地暴露在这了,而且说出mmc_request就是他的请求处理的函数这个石破天惊的秘籍。

128行我们平时用的很少,一般没有为请求队列定义准备函数。这里定义了mmc_prep_request来做之前的工作主要是为了过滤掉一些不合理的块请求,相关的代码比较简单如下:

[card/queue.c]

29   static int mmc_prep_request(struct request_queue *q, struct request *req)        

30   {           

31          /*   

32          * We only like normal block requests.

33          */  

34          if (!blk_fs_request(req)) {    

35                 blk_dump_rq_flags(req, "MMC bad request");

36                 return BLKPREP_KILL;

37          }    

38                 

39          req->cmd_flags |= REQ_DONTPREP;

40                 

41          return BLKPREP_OK;  

42   }    

129行为实现屏蔽请求服务。

132-178行是为请求平衡服务的,飘过...

181-186行根据主机控制器的特性来设置请求队列的一些属性。

189-194行散列存储结构struct scatterlist的申请与初始化。

199行创建并启动内核线程,关于这个线程所做的工作,后面我们会详细介绍。

如果不出意外,mmc_init_queue就该是返回了,重新回到mmc_blk_alloc

508行这句话单独提出来md->queue.issue_fn = mmc_blk_issue_rq,可见他的作用重大,后面讲到上面创建的那个内核进程的时候我会对他详细分析。现在留点印象....

509-516行对gendisk做些常规的赋值工作,就不再一一叙述了。

530-546行设置gendisk的名字,逻辑扇区的大小保持与硬件一致等工作,为add_disk作准备。

mmc_blk_data涵盖的内容较多,mmc_blk_alloc分配完相应的结构以后进行了必要的初始化,后面如果时机成熟驱动将调用add_disk完成mmc_blk_data->disk的真正注册。回到mmc_blk_probe....

601mmc_blk_set_blksize,跟踪源码....

[card/block.c]

558 static int               

559 mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)              

560 {                  

561        struct mmc_command cmd;         

562        int err;          

563                      

564        /* Block-addressed cards ignore MMC_SET_BLOCKLEN. */          

565        if (mmc_card_blockaddr(card))          

566               return 0; 

567                      

568        mmc_claim_host(card->host);             

569        cmd.opcode = MMC_SET_BLOCKLEN;           

570        cmd.arg = 512;            

571        cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;            

572        err = mmc_wait_for_cmd(card->host, &cmd, 5);       

573        mmc_release_host(card->host);           

574                      

575        if (err) {        

576               printk(KERN_ERR "%s: unable to set block size to %d: %d\n",      

577                      md->disk->disk_name, cmd.arg, err);

578               return -EINVAL;   

579        }           

580                      

581        return 0;        

582 }           

这个函数表面上看上去平静的不得了,但是里面却是暗流汹涌。曾几何时为这个函数是否要现在分析,纠结了N久。其中的关系那是错综复杂、意乱情迷,每个函数的实现又是扑朔迷离。但有一点是肯定的,这个函数我们早晚得看,而且还要看的非常细致。不因他在整个故事发展过程中有多重要,只是他使用的手段过于犀利。好了,闲话少说....

561行又是一个新的数据结构struct mmc_command,此时此刻我是多么想说清楚这个结构的真正内涵,但现实告诉我这是说不完的,否则等整个故事讲完可能我们还停留在card目录下,总之现在还不是说它最好的时候,后面会有机会来和他做个了断。

565mmc_card_blockaddr()实则是个宏定义:

#define mmc_card_blockaddr(c)   ((c)->state & MMC_STATE_BLOCKADDR)

既然说不清struct mmc_command那也就理不顺这个的真正含义了。但是有一点是可以肯定的mmc_blk_set_blksize就是来设置SD的扇区大小的,既然人家都不支持这个功能(扇区大小设置),那这个函数继续下去也就没什么意义了。

568行这是core那边的一个函数mmc_claim_host,明理人估计一眼就看的出来这是在获取一个主机的控制器。我们知道一个控制器可能服务多个对象,现在要想使用它来对SD卡的扇区进行设置,那么首先我们必须先获得他老人家的同意。相信只要不是个强盗,这点道德还是应该懂得的。好了,至于这个中间是否还要经过九九八十一难,单凭这个函数名就不得而知了。姑且记下它,等到看到core的时候少不了和他打交道。

569-571行虽说struct mmc_command我们还没说,但是单从一点英文基础就可以看出来cmd.opcode = MMC_SET_BLOCKLEN;表示命令的操作码是设定扇区大小的。

cmd.arg = 512;参数是512

572行又是core那边的函数,名字就能看出他是把刚才这个设置扇区大小的任务交个host去完成,至于到底是怎么完成的你现在大可不必知道,谁叫俺们现在还在card目录下呢。不过要提醒一下的是,这个函数可不是一盏省油的灯。

573行见他长相和mmc_ claim _host相像,八成估计两个都是唱戏的,一个唱白脸一个唱红脸。mmc_ claim _host是要获得主机控制器,那么mmc_release_host人如其名也就是释放控制器了。

鉴于这个函数的特殊性,还是来稍稍总结一下。首先,许多SD而言这里函数可有可无,毕竟扇区不以512为大小的可能还是少数。另外,关键是里面牵扯到三个重要函数:

l  mmc_claim_host(card->host);

l  err = mmc_wait_for_cmd(card->host, &cmd, 5);

l  mmc_release_host(card->host);

走完mmc_blk_set_blksize就又该回到mmc_blk_probe了,接着往下走....

605-609string_get_size这个函数天生就是个无聊,既然存在就又价值,他就是把获取到的容量信息转化成字符串的形式放在char cap_str[10];中好让printk来打印。

611#define mmc_set_drvdata(c,d)    dev_set_drvdata(&(c)->dev, d),又是玩暧昧的,你中有我,我中有你.....

612行十月革命一声炮响,给我们送来了马克思列宁主义。而add_disk这一炮也具有跨时代的意义,给SD卡设备带来了改革开放。这也就意味着SD卡可以正式投入使用了.....

如果一切都是命中注定,那相信mmc_blk_probe也该返回了,但card目录的任务还远没有完成。

2.     do_request

       有句话说的好,“出来混,早晚是要还的”。还记得我们分析probe方法的时候中间有这么一段调用mmc_blk_probe->mmc_blk_alloc->mmc_init_queue->blk_init_queue,其调用的原型如下:

121 mq->queue = blk_init_queue(mmc_request, lock);     

122 if (!mq->queue)    

123        return -ENOMEM;

124        

125 mq->queue->queuedata = mq;

       当时说后面再详细分析,现在可谓是时机成熟。那么我们就先来一睹她的芳容....

[card/queue.c]

81   /*                 

82   * Generic MMC request handler.  This is called for any queue on a              

83   * particular host.  When the host is not busy, we look for a request              

84   * on any queue on this host, and attempt to issue it.  This may                    

85   * not be the queue we were asked to process.                  

86   */                

87   static void mmc_request(struct request_queue *q)                    

88   {                  

89          struct mmc_queue *mq = q->queuedata;            

90          struct request *req;       

91                        

92          if (!mq) {             

93                 printk(KERN_ERR "MMC: killing requests for dead queue\n");

94                 while ((req = blk_fetch_request(q)) != NULL)   

95                        __blk_end_request_all(req, -EIO);

96                 return;    

97          }           

98                        

99          if (!mq->req)        

100               wake_up_process(mq->thread);    

101 }

92-97行出错的处理我们就不多研究了.....

99-100行人分两类一类是会干活的,没话说真正的老黄牛;另一类则是会利用别人来干活的。这里的情况明显属于后者,至于这个被利用的对象就要追溯到mq->thread      这个对象了。没办法往上搜索一下mq->thread,显然在       card/queue.c199行给了我们一个天大的提示:

199 mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd");

前面说过,这是创建一个内核线程与之相关的还有:

1kthread_create创建线程:

struct task_struct *kthread_create(int(*threadfn)(void *data), void *data,const char *namefmt, ...);

这个函数可以像printk一样传入某种格式的线程名线程创建后,不会马上运行,而是需要将kthread_create()返回的task_struct指针传给wake_up_process()然后通过此函数运行线程。

2. 当然,还有一个创建并启动线程的函数:kthread_run

   struct task_struct *kthread_run(int (*threadfn)(void *data),void*data,constchar *namefmt, ...);

线程一旦启动起来后,会一直运行,除非该线程主动调用do_exit函数,或者其他的进程调用kthread_stop函数,结束线程的运行。

    int kthread_stop(struct task_struct *thread);

kthread_stop() 通过发送信号给线程。

如果线程函数正在处理一个非常重要的任务,它不会被中断的。当然如果线程函数永远不返回并且不检查信号,它将永远都不会停止。

这里先来看一下mmc_queue_thread,由于源码比较长分析过程分段进行,相关源码如下:

[card/queue.c]

44   static int mmc_queue_thread(void *d)                      

45   {                         

46          struct mmc_queue *mq = d;               

47          struct request_queue *q = mq->queue;               

48                               

49          current->flags |= PF_MEMALLOC;                  

50                               

51          down(&mq->thread_sem);                 

52          do {              

53                 struct request *req = NULL;        

54                               

55                 spin_lock_irq(q->queue_lock);           

56                 set_current_state(TASK_INTERRUPTIBLE);            

57                 if (!blk_queue_plugged(q))         

58                        req = blk_fetch_request(q);  

59                 mq->req = req;            

60                 spin_unlock_irq(q->queue_lock);        

61                               

62                 if (!req) {             

63                        if (kthread_should_stop()) { 

64                               set_current_state(TASK_RUNNING);

65                               break;

66                        }    

67                        up(&mq->thread_sem); 

68                        schedule();     

69                        down(&mq->thread_sem);   

70                        continue;

71                 }           

72                 set_current_state(TASK_RUNNING);         

73                               

74                 mq->issue_fn(mq, req);       

75          } while (1);                 

76          up(&mq->thread_sem);               

77                               

78          return 0;               

79   }                         

kthread_run创建线程并运行,同时mq->thread_sem这个线程锁保证当前线程执行的原子性

51行获取这个线程的信号量;

56行设置当前线程运行状态为可中断的,当设置该状态以后内核在下一次调度时将该线程置为睡眠。除非其他线程唤醒。这里由于上下文处于原子态,所以只有等到68行以后内核才会发起调度。

57-58行块设备层的函数用于取出请求结构。同样55行和60行维护了一个队列锁,保证请求队列的原子性。

62-66如果请求不存在,同时其他线程发送了终止线程的请求那么直接跳出while循环也就意味着线程走到了生命的尽头。

68行如果没有请求存在,那么内核线程将进入睡眠

74行早在mmc_blk_alloc中有这么一个初始化的动作   

508                 md->queue.issue_fn = mmc_blk_issue_rq;

这里的mmc_blk_issue_rq定义在card/block.c中,原型如下:

[card/block.c]

237 static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)                      

238 {                                

239        struct mmc_blk_data *md = mq->data;                     

240        struct mmc_card *card = md->queue.card;                       

241        struct mmc_blk_request brq;                      

242        int ret = 1, disable_multi = 0;                           

243                                    

244        mmc_claim_host(card->host);                           

245                                    

246        do {                     

247               struct mmc_command cmd;                

248               u32 readcmd, writecmd, status = 0;                   

249                                    

250               memset(&brq, 0, sizeof(struct mmc_blk_request));                  

251               brq.mrq.cmd = &brq.cmd;                 

252               brq.mrq.data = &brq.data;                  

253                                    

254               brq.cmd.arg = blk_rq_pos(req);                 

255               if (!mmc_card_blockaddr(card))                

256                      brq.cmd.arg <<= 9;             

257               brq.cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;               

258               brq.data.blksz = 512;                  

259               brq.stop.opcode = MMC_STOP_TRANSMISSION;                 

260               brq.stop.arg = 0;                 

261               brq.stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;  

262               brq.data.blocks = blk_rq_sectors(req);               

263                                    

264               /*                 

265               * The block layer doesn't support all sector count                   

266               * restrictions, so we need to be prepared for too big               

267               * requests.                 

268               */                

269               if (brq.data.blocks > card->host->max_blk_count)                   

270                      brq.data.blocks = card->host->max_blk_count;          

271                                    

272               /*                 

273               * After a read error, we redo the request one sector at a time                 

274               * in order to accurately determine which sectors can be read                 

275               * successfully.                   

276               */                

277               if (disable_multi && brq.data.blocks > 1)                 

278                      brq.data.blocks = 1;             

279                                    

280               if (brq.data.blocks > 1) {                   

281                      /* SPI multiblock writes terminate using a special             

282                      * token, not a STOP_TRANSMISSION request.             

283                      */         

284                      if (!mmc_host_is_spi(card->host)        

285                                    || rq_data_dir(req) == READ)

286                             brq.mrq.stop = &brq.stop;    

287                      readcmd = MMC_READ_MULTIPLE_BLOCK;        

288                      writecmd = MMC_WRITE_MULTIPLE_BLOCK;            

289               } else {                

290                      brq.mrq.stop = NULL;         

291                      readcmd = MMC_READ_SINGLE_BLOCK;            

292                      writecmd = MMC_WRITE_BLOCK;          

293               }                  

294                                    

295               if (rq_data_dir(req) == READ) {               

296                      brq.cmd.opcode = readcmd;        

297                      brq.data.flags |= MMC_DATA_READ;       

298               } else {                

299                      brq.cmd.opcode = writecmd;       

300                      brq.data.flags |= MMC_DATA_WRITE;             

301               }                  

302                                    

303               mmc_set_data_timeout(&brq.data, card);                  

304                                    

305               brq.data.sg = mq->sg;                 

306               brq.data.sg_len = mmc_queue_map_sg(mq);                    

307                                    

308               /*                 

309               * Adjust the sg list so it is the same size as the                

310               * request.                   

311               */                

312               if (brq.data.blocks != blk_rq_sectors(req)) {                    

313                      int i, data_size = brq.data.blocks << 9;       

314                      struct scatterlist *sg;            

315                                    

316                      for_each_sg(brq.data.sg, sg, brq.data.sg_len, i) {       

317                             data_size -= sg->length;

318                             if (data_size <= 0) {     

319                                    sg->length += data_size;

320                                    i++;

321                                    break;

322                             }    

323                      }           

324                      brq.data.sg_len = i;       

325               }                  

326                                    

327               mmc_queue_bounce_pre(mq);                   

328                                    

329               mmc_wait_for_req(card->host, &brq.mrq);              

330                                    

331               mmc_queue_bounce_post(mq);                  

332                                    

333               /*                 

334               * Check for errors here, but don't jump to cmd_err                

335               * until later as we need to wait for the card to leave               

336               * programming mode even when things go wrong.                 

337               */                

338               if (brq.cmd.error || brq.data.error || brq.stop.error) {                

339                      if (brq.data.blocks > 1 && rq_data_dir(req) == READ) {        

340                             /* Redo read one sector at a time */     

341                             printk(KERN_WARNING "%s: retrying using single "      

342                                    "block read\n", req->rq_disk->disk_name);   

343                             disable_multi = 1; 

344                             continue;

345                      }           

346                      status = get_card_status(card, req);             

347               }                  

348                                    

349               if (brq.cmd.error) {                    

350                      printk(KERN_ERR "%s: error %d sending read/write "           

351                             "command, response %#x, card status %#x\n",            

352                             req->rq_disk->disk_name, brq.cmd.error,            

353                             brq.cmd.resp[0], status);        

354               }                  

355                                    

356               if (brq.data.error) {                    

357                      if (brq.data.error == -ETIMEDOUT && brq.mrq.stop)            

358                             /* 'Stop' response contains card status */      

359                             status = brq.mrq.stop->resp[0];    

360                      printk(KERN_ERR "%s: error %d transferring data,"       

361                             " sector %u, nr %u, card status %#x\n",       

362                             req->rq_disk->disk_name, brq.data.error,            

363                             (unsigned)blk_rq_pos(req),           

364                             (unsigned)blk_rq_sectors(req), status);         

365               }                  

366                                    

367               if (brq.stop.error) {                    

368                      printk(KERN_ERR "%s: error %d sending stop command, "           

369                             "response %#x, card status %#x\n",             

370                             req->rq_disk->disk_name, brq.stop.error,            

371                             brq.stop.resp[0], status);        

372               }                  

373                                    

374               if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {              

375                      do {       

376                             int err;   

377                                    

378                             cmd.opcode = MMC_SEND_STATUS;

379                             cmd.arg = card->rca << 16;  

380                             cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 

381                             err = mmc_wait_for_cmd(card->host, &cmd, 5);

382                             if (err) { 

383                                    printk(KERN_ERR "%s: error %d requesting status\n",

384                                           req->rq_disk->disk_name, err);

385                                    goto cmd_err;

386                             }    

387                             /*   

388                             * Some cards mishandle the status bits,     

389                             * so make sure to check both the busy

390                             * indication and the card state.   

391                             */  

392                      } while (!(cmd.resp[0] & R1_READY_FOR_DATA) ||             

393                             (R1_CURRENT_STATE(cmd.resp[0]) == 7));    

394                                    

395 #if 0                                  

396                      if (cmd.resp[0] & ~0x00000900)        

397                             printk(KERN_ERR "%s: status = %08x\n",

398                                    req->rq_disk->disk_name, cmd.resp[0]);      

399                      if (mmc_decode_status(cmd.resp))             

400                             goto cmd_err;

401 #endif                                

402               }                  

403                                   

404               if (brq.cmd.error || brq.stop.error || brq.data.error) {                

405                      if (rq_data_dir(req) == READ) {        

406                             /*   

407                             * After an error, we redo I/O one sector at a     

408                             * time, so we only reach here after trying to     

409                             * read a single sector.  

410                             */  

411                             spin_lock_irq(&md->lock);  

412                             ret = __blk_end_request(req, -EIO, brq.data.blksz);   

413                             spin_unlock_irq(&md->lock);     

414                             continue;

415                      }           

416                      goto cmd_err;       

417               }                  

418                                    

419               /*                 

420               * A block was successfully transferred.                    

421               */                

422               spin_lock_irq(&md->lock);                

423               ret = __blk_end_request(req, 0, brq.data.bytes_xfered);                   

424               spin_unlock_irq(&md->lock);                   

425        } while (ret);                      

426                                    

427        mmc_release_host(card->host);                         

428                                    

429        return 1;                      

430                                    

431 cmd_err:                                  

432      /*                        

433       * If this is an SD card and we're writing, we can first                           

434       * mark the known good sectors as ok.                     

435       *                        

436        * If the card is not SD, we can still ok written sectors                           

437        * as reported by the controller (which might be less than                      

438        * the real number of written sectors, but never more).                          

439        */                       

440        if (mmc_card_sd(card)) {                          

441               u32 blocks;                  

442                                    

443               blocks = mmc_sd_num_wr_blocks(card);                  

444               if (blocks != (u32)-1) {               

445                      spin_lock_irq(&md->lock);         

446                      ret = __blk_end_request(req, 0, blocks << 9);           

447                      spin_unlock_irq(&md->lock);            

448               }                  

449        } else {                       

450               spin_lock_irq(&md->lock);                

451               ret = __blk_end_request(req, 0, brq.data.bytes_xfered);                   

452               spin_unlock_irq(&md->lock);                   

453        }                         

454                                    

455        mmc_release_host(card->host);                         

456                                    

457        spin_lock_irq(&md->lock);                       

458        while (ret)                          

459               ret = __blk_end_request(req, -EIO, blk_rq_cur_bytes(req));                   

460        spin_unlock_irq(&md->lock);                          

461                                    

462        return 0;                      

463 }                  

244mmc_claim_host之前已经简单介绍过来,后面再说。

250行出现一个struct mmc_blk_request其定义如下:

struct mmc_blk_request {

       struct mmc_request        mrq;

       struct mmc_command    cmd;

       struct mmc_command    stop;

       struct mmc_data            data;

};

struct mmc_request是将要传递给corehost层的一个mmc封装的请求,而其中的定义均为指针变量。这里正好定义一个局部的mmc_blk_request里面同时包含

struct mmc_commandstruct mmc_commandstruct mmc_data变量,当请求完成时函数结束,对应的变量也就销毁了。

251-252行正好与后面286290行相对应形成一组struct mmc_request结构。

254获取操作的开始扇区号。

256行写入命令的参数,对应SD卡地址第九位为0

259-261行对停止命令的相关设置。

262行获取要传送的扇区数目。

269-270行如果需要传输的扇区数目大于主机控制器允许的最大数目时,以硬件的最大容量为准。

277-278行当多扇区读取失败时会置位disable_multi=1,驱动会重新以单个散区的形式读取SD卡。

280-301行设置正确的读写命令,代码比较简单就不详细说明了。

303core层部分的代码,作用是根据不同的操作和卡的信息来设置适当的brq.data.timeout_ns,操作超时时间。具体的代码如下:

[core/core.c]

246 void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)         

247 {                                

248        unsigned int mult;                      

249                                    

250        /*                        

251        * SDIO cards only define an upper 1 s limit on access.                         

252        */                       

253        if (mmc_card_sdio(card)) {                       

254               data->timeout_ns = 1000000000;               

255               data->timeout_clks = 0;              

256               return;                  

257        }                         

258                                    

259        /*                        

260        * SD cards use a 100 multiplier rather than 10                       

261        */                       

262        mult = mmc_card_sd(card) ? 100 : 10;                     

263                                    

264        /*                        

265        * Scale up the multiplier (and therefore the timeout) by                        

266        * the r2w factor for writes.                      

267        */                       

268        if (data->flags & MMC_DATA_WRITE)                         

269               mult <<= card->csd.r2w_factor;                

270                                    

271        data->timeout_ns = card->csd.tacc_ns * mult;                         

272        data->timeout_clks = card->csd.tacc_clks * mult;                           

273                                    

274        /*                        

275        * SD cards also have an upper limit on the timeout.                      

276        */                       

277        if (mmc_card_sd(card)) {                          

278               unsigned int timeout_us, limit_us;              

279                                    

280               timeout_us = data->timeout_ns / 1000;              

281               timeout_us += data->timeout_clks * 1000 /               

282                      (card->host->ios.clock / 1000);           

283                                    

284               if (data->flags & MMC_DATA_WRITE)                  

285                      /*          

286                      * The limit is really 250 ms, but that is            

287                      * insufficient for some crappy cards.        

288                      */         

289                      limit_us = 300000;       

290               else               

291                      limit_us = 100000;       

292                                    

293               /*                 

294               * SDHC cards always use these fixed values.                  

295               */                

296               if (timeout_us > limit_us || mmc_card_blockaddr(card)) {               

297                      data->timeout_ns = limit_us * 1000;          

298                      data->timeout_clks = 0;       

299               }                  

300        }                         

301        /*                        

302        * Some cards need very high timeouts if driven in SPI mode.                      

303        * The worst observed timeout was 900ms after writing a                       

304        * continuous stream of data until the internal logic                        

305        * overflowed.                           

306        */                       

307        if (mmc_host_is_spi(card->host)) {                          

308               if (data->flags & MMC_DATA_WRITE) {                

309                      if (data->timeout_ns < 1000000000)          

310                             data->timeout_ns = 1000000000;  /* 1s */

311               } else {                

312                      if (data->timeout_ns < 100000000)            

313                             data->timeout_ns =  100000000; /* 100ms */

314               }                  

315        }                         

316 }                                

上面代码对时间处理比较细致,程序实现也比较简单,就不再详细说明了。重新回到mmc_blk_issue_rq....

305-306行这两行关于scatterlist的操作,比较关键。具体的实现如下:

[card/queue.c]

301 unsigned int mmc_queue_map_sg(struct mmc_queue *mq)       

302 {           

303        unsigned int sg_len;      

304        size_t buflen; 

305        struct scatterlist *sg;     

306        int i;      

307               

308        if (!mq->bounce_buf)   

309               return blk_rq_map_sg(mq->queue, mq->req, mq->sg);

310               

311        BUG_ON(!mq->bounce_sg);

312               

313        sg_len = blk_rq_map_sg(mq->queue, mq->req, mq->bounce_sg);    

314               

315        mq->bounce_sg_len = sg_len;      

316               

317        buflen = 0;    

318        for_each_sg(mq->bounce_sg, sg, sg_len, i) 

319               buflen += sg->length;

320               

321        sg_init_one(mq->sg, mq->bounce_buf, buflen); 

322               

323        return 1; 

324 }           

之前的分析中我们忽略了bounce_buf机制,所以这里真正关心的是308-309行。使用给定请求的全部段填充给定的散列表,同时内存中邻近的段在插入散布表之前被接合,对应sg_len返回的是散列表的项数。这样以后提交给coremmc_request结构中就可以直接使用scatterlist。然而对于bounce_buf机制下的scatterlist318-319行将所有的操作整合以后最终调用321行的sg_init_one只初始化一个散列表项。后面我们将看到他们跟进一步的区别。是时候回到mmc_blk_issue_rq中了。

312-325行代码比较简单,316行遍历sg list,获取其数据长度,最终根据实际请求的大小作比较,来调整sg list的大小及项数。

327331行这是和bounce_buf机制相关的,有兴趣的可以参考源码。

329行起来一个承上启下的作用,同时也将整个card目录推向了故事的高潮。与前面所说的mmc_wait_for_cmd一样,这里是很难说清楚mmc_wait_for_req的实现了。他是core层的一个接口函数,这里我们关注他说传递的两个参数mmc_wait_for_req(card->host, &brq.mrq);

card->host对应请求的主机控制器,然后,请求要做的事情就包含在brq.mrq当中了。递交完这两项内容以后,之前说过的那个内核线程就可以安然入睡了,至于什么时候被什么吵醒后面我们遇到了再来分析。

331行以后发生的故事也许就只能等到线程醒来的时候才知道了。但是有些时候还是要有点未卜先知的能力的,显然下面这段基本都是在处理出错的一些状态,还是简单分析一下....

338行这些个error不是被人干的,正是调用mmc_wait_for_req以后,底层的host主机控制器传送上来的。

343行很明显前面已经说过了,这斯出错了还不承认,还说人家让他传送的扇区多了,还有一个一个扇区来做。好吧,就给你这个机会,结果就置位了disable_multi,接着continue

346行能走到这里的哥们可能就不得不承认自己错了,好吧没有办法就去找出错的原因吧,也就只能读取设备的状态信息了。

[card/block.c]

220 static u32 get_card_status(struct mmc_card *card, struct request *req)            

221 {           

222        struct mmc_command cmd;  

223        int err;   

224               

225        memset(&cmd, 0, sizeof(struct mmc_command));     

226        cmd.opcode = MMC_SEND_STATUS;

227        if (!mmc_host_is_spi(card->host))      

228               cmd.arg = card->rca << 16;

229        cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;     

230        err = mmc_wait_for_cmd(card->host, &cmd, 0);

231        if (err)   

232               printk(KERN_ERR "%s: error %d sending status comand",

233                      req->rq_disk->disk_name, err);

234        return cmd.resp[0];

235 }

相信这段代码还是有点熟悉的了,这里就不必详说了,注意这里少了一个申请主机控制器的动作,因为前面申请到的还没释放呢。

349-372行有了出错的状态那就慢慢分析了,无非是prinkt

374-393行主要是为了满足时序上的要求,具体内容后面会根据SD spece中的内容来做分析。

404-417行如果程序执行到这里,那么这个设备可能就真没得救了。早点goto cmd_err吧。

420-424行这段是最好的结果了,           

ret = __blk_end_request(req, 0, brq.data.bytes_xfered);

提交给块层,请求处理成功。当然这也是我们最想见到的,至于cmd_err:以后的内容,这里就没有必要再详细分析了,有兴趣研究的自己琢磨。

3.     小结

       好了,card的故事该说的,能说的到这里就算是讲完了。稍微回顾一下这一层所做的工作,就是将块层递交的请求从新打包成mmc_request递交出去,其中块层请求处理为了提高性能采用了内核线程的方法。为了后面分析方便还是列出部分与core层的接口函数:

l  static inline void mmc_claim_host(struct mmc_host *host)

l  void mmc_release_host(struct mmc_host *host)

l  void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)

l  int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries)

最后,带着N多的困惑与不解继续走向core层的春天.....

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值