日期:2014-05-16  浏览次数:20895 次

写一个以太网驱动,在hard_start_xmit中访问dev->priv中的成员,出现崩溃
struct net_device *veth_devs[VETH_NUM];

static int
veth_open(struct net_device *dev)
{
veth_private_s *vep ;

vep = (veth_private_s *)dev->priv;

vep->dev = dev; /*Remember dev in veth_private_s*/

queue_delayed_work(vep->rx_poll, &vep->rx_poll_task, POLL_SPEED);

netif_start_queue(dev);

printk(KERN_ALERT "%s: %s \r\n", dev->name, __FUNCTION__);

return 0; /* Always succeed */
}

static int
veth_close(struct net_device *dev)
{
veth_private_s *vep ;

vep = (veth_private_s *)dev->priv;

netif_stop_queue(dev);

flush_workqueue(vep->rx_poll);
cancel_delayed_work(&vep->rx_poll_task); 

printk(KERN_ALERT "%s: %s \r\n", dev->name, __FUNCTION__);

return 0;
}

#if 1
static int
veth_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
int i;
char *p;
char tmp[4];

veth_private_s *vep = (veth_private_s *)dev->priv;

printk(KERN_ALERT "%s: %s \r\n", dev->name, __FUNCTION__);

vep->rx_buff = (unsigned char *)kmalloc(VETH_RX_BUFFSIZE, GFP_KERNEL);

memset(vep->rx_buff, 0, VETH_RX_BUFFSIZE);

memcpy(vep->rx_buff, skb->data, skb->len); //这里出现崩溃,系统重启
#if 0
p = vep->rx_buff;
//p = skb->data;

if(skb->len > 0){
printk(KERN_ALERT "%s: veth_start_xmit len=%d \r\n", dev->name, skb->len);

for(i=0; i<skb->len; i++){
if(i%20 == 0)
printk(KERN_ALERT "\r\n");
else{
memset(tmp, 0, 4);
sprintf(tmp, "%d", vep->rx_buff[i]);
printk(KERN_ALERT "%d,%s,%d ", i, tmp, vep->rx_buff[i]);
}
}
printk("\r\n");
}
#endif

dev_kfree_skb(skb);

return 0; /* Our simple device can not fail */
}
#endif

static void veth_rx_poll(struct work_struct *work)
{
veth_private_s *vep = 
container_of(work, veth_private_s, rx_poll_task.work);

struct net_device *dev = vep->dev;

printk(KERN_ALERT "%s: %s \r\n", dev->name, __FUNCTION__);

//dev_kfree_skb(skb);

queue_delayed_work(vep->rx_poll, &vep->rx_poll_task, POLL_SPEED);
}

void veth_init(struct net_device *dev)
{
veth_private_s *vep;
bd_t *bd;
int i;
static char mc_addr4 = 0x0;
static char mc_addr5 = 0x0;

bd = (bd_t *)__res;

/*
* Make the usual checks: check_region(), probe irq, ... -ENODEV
* should be returned if no device found. No resource should be
* grabbed: this is done on open(). 
*/

ether_setup(dev); /* assign some of the fields */

dev->open = veth_open;
dev->stop = veth_close;
dev->hard_start_xmit = veth_start_xmit;
dev->watchdog_timeo = TX_TIMEOUT;

/*
dev->set_config = snull_config;
dev->do_ioctl = snull_ioctl;
dev->get_stats = snull_stats;
dev->change_mtu = snull_change_mtu;  
dev->rebuild_header = snull_rebuild_header;
dev->hard_header = snull_header;
dev->tx_timeout = snull_tx_timeout;
dev->watchdog_timeo = timeout;
*/

/* keep the default flags, just add NOARP */
dev->flags |= IFF_NOARP;
dev->features |= NETIF_F_NO_CSUM;
dev->hard_header_cache = NULL; /* Disable caching */

vep = netdev_priv(dev);
//vep->rx_buff = (unsigned char *)kmalloc(VETH_RX_BUFFSIZE, GFP_KERNEL)