当前位置: 首页 > news >正文

inurl 湖北网站建设/惠州网络营销

inurl 湖北网站建设,惠州网络营销,电影资源网站怎么做的,石家庄个人建网站最近做的一个项目,系统启动时发现有warning,并打印出了一堆dump stack。 看了下代码,发现是在esai的probe函数中调用request_mem_region时失败代码走到了错误处理的部分。 错误处理中disable了一个clock,warning的内容是说该clock…

最近做的一个项目,系统启动时发现有warning,并打印出了一堆dump stack。
看了下代码,发现是在esai的probe函数中调用request_mem_region时失败代码走到了错误处理的部分。
错误处理中disable了一个clock,warning的内容是说该clock没enable就disable了。

从代码看,存在两个问题:
1、request_mem_region为什么会失败。
2、为什么在disable clock之前没有enable。

先看看request_mem_region为什么会失败。
经大牛指点,request_mem_region失败,应该是因为申请的一块内存,部分/全部已被占用,所以导致申请失败。
为了看看申请的内存是否与其他io申请的内存释放有冲突,将/proc/iomem文件cat出来,发现esai申请的内存与ssi-0申请的内存重叠。
对照cpu的reference manual,发现esai很守规矩,使用的是memory map中给自己指定的memory范围;而ssi-0没使用memory map中指定的内存范围,抢占了esai的内存范围。
找到esai base address和ssi-0(对应的是硬件ssi-1) base address定义,发现定义没问题,与memory map中一致。
在esai和ssi的probe函数中加log,发现首先是ssi-1申请了正确的内存,ssi-2也申请了正确的内存,接下来ssi-0申请的内存范围是esai的内存范围。
因为ssi在esai前面进行的probe,导致esai申请内存时,内存已经被ssi-0申请了去,所以失败。
可疑点是,ssi的顺序为什么是1、2、0,而不是0、1、2。
看了board文件中添加resource的地方,发现是先添加了ssi 1、2、3,然后添加了esai。
跟了下添加ssi resource的代码,发现知道的序号其实用作了数组下标,数组下标都是从0开始的,这儿为什么是1、2、3?
是不是添加ssi 1\2\3的时候,1、2没问题,由于ssi只有0\1\2,添加3的时候,抢占了esai的位置。
将board中的ssi 1\2\3改为0\1\2,果然问题解决。

若只是止步于此,少了些乐趣。
不仅要知其然,也要知其所以然。

先看看request_mem_region的实现。

#define request_mem_region(start, n, name) __request_region(&iomem_resource, (start), (n), (name), 0)


看看iomem_resource的定义:

struct resource iomem_resource = {.name	= "PCI mem",.start	= 0,.end	= -1,.flags	= IORESOURCE_MEM,
};


resource type有以下几种类型:

#define IORESOURCE_IO		0x00000100
#define IORESOURCE_MEM		0x00000200
#define IORESOURCE_IRQ		0x00000400
#define IORESOURCE_DMA		0x00000800
#define IORESOURCE_BUS		0x00001000


看看__request_region的实现:

/*** __request_region - create a new busy resource region* @parent: parent resource descriptor* @start: resource start address* @n: resource region size* @name: reserving caller's ID string* @flags: IO resource flags*/
struct resource * __request_region(struct resource *parent,resource_size_t start, resource_size_t n,const char *name, int flags)
{// 定义并初始化一个wait queue/*#define DECLARE_WAITQUEUE(name, tsk)					\wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk)*//*#define __WAITQUEUE_INITIALIZER(name, tsk) {				\.private	= tsk,						\.func		= default_wake_function,			\.task_list	= { NULL, NULL } }*/DECLARE_WAITQUEUE(wait, current);/*
/** Resources are tree-like, allowing* nesting etc..*/
struct resource {resource_size_t start;resource_size_t end;const char *name;unsigned long flags;struct resource *parent, *sibling, *child;
};*//*
/*** kzalloc - allocate memory. The memory is set to zero.* @size: how many bytes of memory are required.* @flags: the type of memory to allocate (see kmalloc).*/
static inline void *kzalloc(size_t size, gfp_t flags)
{return kmalloc(size, flags | __GFP_ZERO);
}*/struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);if (!res)return NULL;res->name = name;res->start = start;res->end = start + n - 1;res->flags = IORESOURCE_BUSY;res->flags |= flags;write_lock(&resource_lock);for (;;) {struct resource *conflict;// 检查申请的内存与其他内存是否冲突/×
/* Return the conflict entry if you can't request it */
static struct resource * __request_resource(struct resource *root, struct resource *new)
{resource_size_t start = new->start;resource_size_t end = new->end;struct resource *tmp, **p;// 头比尾大,自相矛盾if (end < start)return root;// 头还在根的头前面,越界了if (start < root->start)return root;// 尾在根的尾后面,也越界了if (end > root->end)return root;// 从下面的循环看,root的所有child应该是从低地址到高地址依次排开,并通过他们的sibling进行关联。// 刚开始,p指向root的最大孩子,也就是地址最低的,并判断其与new是否冲突。// 若不冲突,通过最大孩子的sibling成员,找到它的下一个兄弟,并判断其与new是否冲突。// 这样依次判断下去,直到找到了一个空child,或者找到的找到的child的start还在new的end之后,也即完全在new之后。p = &root->child;for (;;) {tmp = *p;if (!tmp || tmp->start > end) {new->sibling = tmp;*p = new;new->parent = root;return NULL;}p = &tmp->sibling;if (tmp->end < start)continue;return tmp;}
}×/conflict = __request_resource(parent, res);if (!conflict)break;// 若有冲突,但冲突的不是根,并且conflict的标志并没有说是busy,也就是说并没有被占用,则说明new落在了原来根的一个child的范围内。// 也就是说conflict其实是new的根,那就将conflict赋值为new的根,再次进行冲突检测。if (conflict != parent) {parent = conflict;if (!(conflict->flags & IORESOURCE_BUSY))continue;}// 如果有冲突,并且conflict和new都是可软件多路复用的,则说明暂时是被别人占用了,// 要做到就是把锁释放了,并等待内存被释放if (conflict->flags & flags & IORESOURCE_MUXED) {/*
/** This is compatibility stuff for IO resources.** Note how this, unlike the above, knows about* the IO flag meanings (busy etc).** request_region creates a new busy region.** check_region returns non-zero if the area is already busy.** release_region releases a matching busy region.*/static DECLARE_WAIT_QUEUE_HEAD(muxed_resource_wait);void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
{unsigned long flags;wait->flags &= ~WQ_FLAG_EXCLUSIVE;spin_lock_irqsave(&q->lock, flags);__add_wait_queue(q, wait);spin_unlock_irqrestore(&q->lock, flags);
}static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
{list_add(&new->task_list, &head->task_list);
}*/add_wait_queue(&muxed_resource_wait, &wait);// 释放锁write_unlock(&resource_lock);// TASK_INTERRUPTIBLE是可以被信号和wake_up()唤醒的,当信号到来时,进程会被设置为可运行。// TASK_UNINTERRUPTIBLE只能被wake_up()唤醒。set_current_state(TASK_UNINTERRUPTIBLE);/*
asmlinkage void __sched schedule(void)
{struct task_struct *tsk = current;sched_submit_work(tsk);__schedule();
}static inline void sched_submit_work(struct task_struct *tsk)
{if (!tsk->state)return;/** If we are going to sleep and we have plugged IO queued,* make sure to submit it to avoid deadlocks.*/if (blk_needs_flush_plug(tsk))blk_schedule_flush_plug(tsk);
}*/// 调度函数,不能简单的一笔带过schedule();remove_wait_queue(&muxed_resource_wait, &wait);write_lock(&resource_lock);continue;}/* Uhhuh, that didn't work out.. */kfree(res);res = NULL;break;}write_unlock(&resource_lock);return res;
}


上面有将wait添加到queue,在__release_region中调用了wake_up用来唤醒等待的进程。

/*** __release_region - release a previously reserved resource region* @parent: parent resource descriptor* @start: resource start address* @n: resource region size** The described resource region must match a currently busy region.*/
void __release_region(struct resource *parent, resource_size_t start,resource_size_t n)
{struct resource **p;resource_size_t end;p = &parent->child;end = start + n - 1;write_lock(&resource_lock);for (;;) {struct resource *res = *p;if (!res)break;if (res->start <= start && res->end >= end) {if (!(res->flags & IORESOURCE_BUSY)) {p = &res->child;continue;}if (res->start != start || res->end != end)break;*p = res->sibling;write_unlock(&resource_lock);if (res->flags & IORESOURCE_MUXED)wake_up(&muxed_resource_wait);kfree(res);return;}p = &res->sibling;}write_unlock(&resource_lock);printk(KERN_WARNING "Trying to free nonexistent resource ""<%016llx-%016llx>\n", (unsigned long long)start,(unsigned long long)end);
}


http://www.lbrq.cn/news/1407601.html

相关文章:

  • iview可以做门户网站吗/正规手游代理平台有哪些
  • 广州网站优化服务/cilimao磁力猫
  • 动态网站建设网/体验式营销案例
  • 网站制作哪个软件/搜索引擎有哪些软件
  • 网站留言板模板/问卷调查网站
  • 购物网站开发技术/手机怎么做网站免费的
  • 加盟营销型网站制作/互联网推广话术
  • 网站中文字内容左右切换的js代码/游戏搜索风云榜
  • 自己如何做网站建设/做网络销售感觉自己是骗子
  • joomla 网站建设/百度网址大全官网旧版
  • 帝国cms登录网站/全网营销系统怎么样
  • 徐州seo推广/长春seo优化
  • 郑州新闻网官网/seo服务公司
  • 服装公司 网站怎么做/网络营销师官网
  • 平乡县网站建设平台位置/电商网站开发
  • 莱州网站建设方案/太原seo管理
  • 三水住房和城乡建设局的网站/网站到首页排名
  • 备案的网站程序上传/上海何鹏seo
  • 网站建设课程设计格式/百度收录网站链接入口
  • 室内设计师在哪里找/seo职业发展
  • 点广告挣钱网站有哪些/深圳seo优化排名
  • 做网站开创和中企动力哪家强/打开百度一下的网址
  • 一流的福州网站建设/app推广方案模板
  • 淘宝网作图做网站/啥是网络推广
  • 做窗帘网站/全国疫情最新信息
  • 第一次做网站不知道/百度官方版
  • 网站外链建设需要逐步进行适可优化即可/百度关键词排名用什么软件
  • 武汉做网站公司有哪些/网络广告设计
  • nike网站建设方案/公司营销网站建设
  • 2020互联网公司排名/seo就业
  • 大模型 + 垂直场景:搜索/推荐/营销/客服领域开发新范式与技术实践
  • 旋钮键盘项目---foc讲解(闭环位置控制)
  • MXFP4量化:如何在80GB GPU上运行1200亿参数的GPT-OSS模型
  • 数组实现各类数据结构
  • Linux应用软件编程---多任务(线程)(线程创建、消亡、回收、属性、与进程的区别、线程间通信、函数指针)
  • C语言指针运算题