2009年12月14日 星期一

dma_free_coherent不能在IRQ disabled下跑..

dma_free_coherent不能在IRQ disabled下跑
但是有些東西非得在IRQ時free掉的話
把實際的free移到workqueue來跑即可

ref dev_kfree_skb_any, net_tx_action, completion_queue


LIST_HEAD(tofree_list);
spinlock_t tofree_list_lock=SPIN_LOCK_UNLOCKED;

struct free_param {
struct list_head list;

void* addr;
dma_addr_t dma_addr;
uint32_t size;
};
void free_list_agent_fn(void *data){
struct list_head free_list;
struct free_param *cur,*next;

spin_lock(tofree_list_lock);
list_add(&free_list,&tofree_list);
list_del_init(&tofree_list);
spin_unlock(tofree_list_lock);

list_for_each_entry_safe(cur,next,&free_list,list){
if(cur==&free_list) break;
dma_free_coherent(NULL,cur->size,cur->addr,cur->dma_addr);
list_del(&cur->list);
kfree(cur);
}
}
DECLARE_WORK(free_list_agent,free_list_agent_fn);


void some_free_func(){
if(irqs_disabled()){
struct free_param* fp=kmalloc(sizeof(struct free_param),GFP_KERNEL);
fp->addr=desc_addr;
fp->dma_addr=dma_desc_addr;
fp->size=count*sizeof(dwc_otg_dma_desc_t);

spin_lock(tofree_list_lock);
list_add(&fp->list,&tofree_list);
spin_unlock(tofree_list_lock);

schedule_work(&free_list_agent);
return ;
}
dma_free_coherent(blablabla);
}

沒有留言: