有关驱动程序的SMP问题

zhp_dean 2004-04-02 01:28:11
在linux kernel 2.4.21下开发的驱动程序,如果运行在UP(uniprocessor,单CPU)下,没有问题;如果在SMP(symmetric muti processor,对称多处理,2CPU)下编译并运行,驱动程序的中断处理不能被调用。
这是什么原因,请大虾指教。
下面是我的驱动程序代码:


static ssize_t c0xa_read(struct file * filep,char * buf,size_t count,loff_t *ppos)
{
unsigned long flags;

save_flags(flags);
cli();

//buf contain a errnum
copy_to_user(buf,&c0xa_rb_buffer[0],count);
restore_flags(flags);
return 0;
}

static ssize_t c0xa_write(struct file * filep,const char *buf,size_t count,loff_t *ppos)
{
unsigned long flags;

save_flags(flags);
cli();
copy_from_user(c0xa_rb_buffer,buf,count);
c0xa_Dialog(&c0xa_rb_buffer[0], 384, &c0xa_rb_buffer[0], 384,c0xa_bEncry);
restore_flags(flags);
return 0;
}

static ssize_t c0xa_open(struct inode *inode,struct file * filep)
{
unsigned long flags;

save_flags(flags);
cli();
MOD_INC_USE_COUNT;
restore_flags(flags);
return 0;
}

static ssize_t c0xa_close(struct inode *inode,struct file * filep)
{
unsigned long flags;

save_flags(flags);
cli();
MOD_DEC_USE_COUNT;
restore_flags(flags);
return 0;
}

void c0xa_Dialog(unsigned int *pWrBuf, int nWrNum, unsigned int *pRdBuf, int nRdNum, int bEncry)
{
unsigned int count;
unsigned int ctrl;
unsigned long flags;

save_flags(flags);
cli();
memcpy(c0xa_dma_buffer, pWrBuf, nWrNum << 2);
count = (nWrNum << 16) + nRdNum;
memcpy((void*)(c0xa_membase+DMACNT),&count,4);
c0xa_pPhysicalAddr = virt_to_bus(c0xa_dma_buffer);
memcpy((void*)(c0xa_membase+RXADDR),&c0xa_pPhysicalAddr,4);
memcpy((void*)(c0xa_membase+TXADDR),&c0xa_pPhysicalAddr,4);
if(c0xa_bEncry==0)
ctrl = 0x81800100;
else
ctrl = 0x81800104;
memcpy((void*)(c0xa_membase+DMACTRL),&ctrl,4);
interruptible_sleep_on(&c0xa_wait_on_interrupt);
c0xa_bEncry = 0;
memcpy(pRdBuf, c0xa_dma_buffer, nRdNum << 2);
restore_flags(flags);
return;
}

void c0xa_MemWrite(unsigned long addr, unsigned long val)
{
memcpy((void*)c0xa_membase+addr,&val,4);
}

/*******************************reset card********************************/
void c0xa_ResetCard(void)
{
int delay_int;
c0xa_MemWrite(DMACTRL, 0x80000003); //resetcard

delay_int = INIT_DELAY_COUNT*100;
while (delay_int>0)
delay_int --;
c0xa_MemWrite(DMACTRL, 0x80000000); //unresetcard

delay_int = INIT_DELAY_COUNT*800;
while (delay_int>0)
delay_int --;
delay_int = INIT_DELAY_COUNT*800;
while (delay_int>0)
delay_int --;
delay_int = INIT_DELAY_COUNT*800;
while (delay_int>0)
delay_int --;
}

static int c0xa_ioctl(struct inode *inode,struct file * filep,unsigned int cmd,unsigned long arg)
{
int errNum,BufLen;

switch (cmd)
{
case RESET_COMMAND:
{
/***************reset card*************************/
c0xa_ResetCard();
break;
}
case GET_READABLE_COMMAND:
{
BufLen=c0xa_dma_buffer[0];
errNum=c0xa_dma_buffer[1];
return (BufLen+errNum*65536);
}
case GET_BOOL_ENC_COMMAND:
c0xa_bEncry = 1;
break;
default:
return -1;
}
return 0;
};

static struct file_operations c0xa_fops =
{
owner: THIS_MODULE,
llseek: NULL, /*no lseek*/
read: c0xa_read,
write: c0xa_write,
poll: NULL, /*no readdir*/
ioctl: c0xa_ioctl,
mmap: NULL, /*no mmap*/
open: c0xa_open,
release: c0xa_close,
};

void c0xa_handler(int irq,void *dev_id,struct pt_regs *regs) /*中断处理函数*/
{
/*wake up waiting process*/
int m=0x80000001;
unsigned long flags;
unsigned int irqflag;

save_flags(flags);
cli();
memcpy(&irqflag,(void*)(c0xa_membase+DMACTRL),4 );
if((irqflag & 1) )
;
else
{
restore_flags(flags);
return;
}

memcpy((void *)c0xa_membase+DMACTRL,&m,4);
m = 0x80000000;
memcpy((void *)c0xa_membase+DMACTRL,&m,4);
wake_up_interruptible(&c0xa_wait_on_interrupt);
restore_flags(flags);
return;
}

int init_module(void) /*insmod 在加载此模块时自动调用*/
{
int err;
unsigned long flags;

printk("SJY03-B card driver[Rev:%s] start, waiting please...", SJY03B_DRIVER_VERSION);
save_flags(flags);
cli();
if (pci_present())
{
int result;
unsigned int svidsid;

// printk("\nSearch SJY03 Device ...");
while ( (c0xa_pci_dev = pci_find_device(PCIVID,PCIDID,c0xa_pci_dev)) != NULL )
{
result = pci_read_config_dword(c0xa_pci_dev,0x10,&c0xa_iobase);
if (result != PCIBIOS_SUCCESSFUL)
{
restore_flags(flags);
return -1;
}
if ( check_mem_region(c0xa_iobase, 0x400) == 0 )
break;
}
if ( c0xa_pci_dev == NULL )
{
printk("ERROR: Device is busy or Unable find the device\n");
restore_flags(flags);
return -1;
}
result = pci_read_config_dword(c0xa_pci_dev,0x2c,&svidsid);
if (result != PCIBIOS_SUCCESSFUL)
{
restore_flags(flags);
return -1;
}
result = pci_read_config_byte(c0xa_pci_dev,0x3c,&c0xa_interrupt_handle);
if (result != PCIBIOS_SUCCESSFUL)
{
restore_flags(flags);
return -1;
}
result = pci_write_config_word(c0xa_pci_dev,0x04,6);
if (result != PCIBIOS_SUCCESSFUL){
restore_flags(flags);
printk("ERROR. write 6");
return -1;
}
}
c0xa_IRQ_NUM=c0xa_interrupt_handle;
/************************** set dma ***************************************/
c0xa_dma_buffer = (unsigned int*)kmalloc(4096, GFP_KERNEL|GFP_DMA);
if(c0xa_dma_buffer == NULL)
return -ENOMEM;
memset(c0xa_dma_buffer,0,4096);

if (!request_mem_region(c0xa_iobase, 0x400, "carddrv1"))
{
restore_flags(flags);
kfree(c0xa_dma_buffer);
printk("<1>ERROR FLAG 0.1\n");
return -1;
}
c0xa_membase = (int)ioremap(c0xa_iobase,0x400);
/*--------hold interrupt handler--------------*/
err = request_irq((unsigned int)c0xa_IRQ_NUM,
c0xa_handler,
SA_SHIRQ,
"carddrv1",
c0xa_pci_dev);
if (err)
{
restore_flags(flags);
kfree(c0xa_dma_buffer);
iounmap((void *)c0xa_membase);
release_mem_region(c0xa_iobase, 0x400);
printk("failed! Flag:2\n");
return -1;
}

if (register_chrdev(c0xa_major,"carddrv1",&c0xa_fops))
{
restore_flags(flags);
kfree(c0xa_dma_buffer);
iounmap((void *)c0xa_membase);
release_mem_region(c0xa_iobase, 0x400);
printk("failed! Flag:3\n");
return -1;
}

c0xa_ResetCard();
restore_flags(flags);
printk(" Complete!\n");
return 0;
}

void cleanup_module(void)
{
c0xa_MemWrite(DMACTRL, 0x80000003);
iounmap((void *)c0xa_membase);
release_mem_region(c0xa_iobase, 0x400);
kfree(c0xa_dma_buffer);
free_irq(c0xa_IRQ_NUM,c0xa_pci_dev);
if (unregister_chrdev(c0xa_major,"carddrv1")!=0)
;
}
...全文
46 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhp_dean 2004-04-05
  • 打赏
  • 举报
回复
我自己UP一下

4,436

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧