Originally Posted by dennisdd
(Post 4610115)
I have problem when I do the following:
status = spi_sync(test_dev.spi_device, &test_ctl.msg);
I get the error:
"Unable to handle kernel NULL pointer dereference at virtual address 00000000"
It seem like the problem related to follow when the kernel* try to execute it, this is part of spi_sync() in spi.c
wait_for_completion(&done);
What could cause this issue? The following is my SPI driver code.
Code:
#define SPI_BUFF_SIZE 16
#define USER_BUFF_SIZE 128
#define SPI_BUS 1
#define SPI_BUS_CS1 1
#define SPI_BUS_SPEED 1000000
const char this_driver_name[] = "test";
struct test_control {
struct spi_message msg;
struct spi_transfer transfer;
u8 *tx_buff;
u8 *rx_buff;
};
static struct test_control test_ctl;
struct test_dev {
struct semaphore spi_sem;
struct semaphore fop_sem;
dev_t devt;
struct cdev cdev;
struct class *class;
struct spi_device *spi_device;
char *user_buff;
u8 test_data;
};
static struct test_dev test_dev;
static void test_prepare_spi_message(void)
{
printk(KERN_ALERT "@test_prepare_spi_message\n");
spi_message_init(&test_ctl.msg);
printk(KERN_ALERT "@test_prepare_spi_message p1\n");
/* put some changing values in tx_buff for testing */
test_ctl.tx_buff[0] = test_dev.test_data++;
test_ctl.tx_buff[1] = test_dev.test_data++;
test_ctl.tx_buff[2] = test_dev.test_data++;
test_ctl.tx_buff[3] = test_dev.test_data++;
memset(test_ctl.rx_buff, 0, SPI_BUFF_SIZE);
test_ctl.transfer.tx_buf = test_ctl.tx_buff;
test_ctl.transfer.rx_buf = test_ctl.rx_buff;
test_ctl.transfer.len = 4;
printk(KERN_ALERT "@test_prepare_spi_message p2\n");
spi_message_add_tail(&test_ctl.transfer, &test_ctl.msg);
}
static int test_do_one_message(void)
{
int status;
printk(KERN_ALERT "@test_do_one_message\n");
if (down_interruptible(&test_dev.spi_sem))
return -ERESTARTSYS;
if (!test_dev.spi_device) {
up(&test_dev.spi_sem);
return -ENODEV;
}
test_prepare_spi_message();
printk(KERN_ALERT "@test_do_one_message p1\n");
if(&test_ctl.msg == NULL )
{
printk(KERN_ALERT "@test_do_one_message test_ctl.msg NULL\n");
return -ENODEV;
}
if(test_dev.spi_device !=NULL)
{
status = spi_sync(test_dev.spi_device, &test_ctl.msg);
}
else
{
printk(KERN_ALERT "@test_do_one_message NULL\n");
return -ENODEV;
}
printk(KERN_ALERT "@test_do_one_message p2\n");
up(&test_dev.spi_sem);
return status;
}
static ssize_t test_read(struct file *filp, char __user *buff, size_t count,
loff_t *offp)
{
size_t len;
ssize_t status = 0;
printk(KERN_ALERT "@test_read\n");
if (!buff)
return -EFAULT;
if (*offp > 0)
return 0;
if (down_interruptible(&test_dev.fop_sem))
return -ERESTARTSYS;
if (!test_dev.spi_device)
{
printk(KERN_ALERT "@test_read test_dev.spi_device is NULL\n");
}
else if (!test_dev.spi_device->master)
{
printk(KERN_ALERT "@test_read spi_device->master is NULL\n");
}
else
{
printk(KERN_ALERT "@test_read %s ready on SPI%d.%d\n",
this_driver_name,
test_dev.spi_device->master->bus_num,
test_dev.spi_device->chip_select);
}
//len = strlen(test_dev.user_buff);
printk(KERN_ALERT "@test_read p1\n");
status = test_do_one_message();
if (status)
{
sprintf(test_dev.user_buff,
"test_do_one_message failed : %d\n",
status);
}
else
{
sprintf(test_dev.user_buff,
"Status: %d\nTX: %d %d %d %d\nRX: %d %d %d %d\n",
test_ctl.msg.status,
test_ctl.tx_buff[0], test_ctl.tx_buff[1],
test_ctl.tx_buff[2], test_ctl.tx_buff[3],
test_ctl.rx_buff[0], test_ctl.rx_buff[1],
test_ctl.rx_buff[2], test_ctl.rx_buff[3]);
}
len = strlen(test_dev.user_buff);
if (len < count)
count = len;
if (copy_to_user(buff, test_dev.user_buff, count)) {
printk(KERN_ALERT "test_readoned(): copy_to_user() failed\n");
status = -EFAULT;
} else {
*offp += count;
status = count;
}
up(&test_dev.fop_sem);
return status;
}
static int test_open(struct inode *inode, struct file *filp)
{
int status = 0;
printk(KERN_ALERT "@test_open\n");
if (down_interruptible(&test_dev.fop_sem))
return -ERESTARTSYS;
if (!test_dev.user_buff) {
test_dev.user_buff = kmalloc(USER_BUFF_SIZE, GFP_KERNEL);
if (!test_dev.user_buff)
status = -ENOMEM;
}
up(&test_dev.fop_sem);
return status;
}
static int __devinit test_probe(struct spi_device *spi_device)
{
struct spi_master *spi_master;
int status = 0;
if (down_interruptible(&test_dev.spi_sem))
return -EBUSY;
printk(KERN_ALERT "@test_probe\n");
spi_master = spi_busnum_to_master(SPI_BUS);
if (!spi_master) {
printk(KERN_ALERT "spi_busnum_to_master(%d) returned NULL\n",
SPI_BUS);
printk(KERN_ALERT "Missing modprobe omap2_mcspi?\n");
return -1;
}
spi_device = spi_alloc_device(spi_master);
if (!spi_device) {
put_device(&spi_master->dev);
printk(KERN_ALERT "spi_alloc_device() failed\n");
return -1;
}
spi_device->chip_select = SPI_BUS_CS1;
spi_device->max_speed_hz = SPI_BUS_SPEED;
spi_device->mode = SPI_MODE_0;
spi_device->bits_per_word = 8;
spi_device->irq = -1;
spi_device->controller_state = NULL;
spi_device->controller_data = NULL;
strlcpy(spi_device->modalias, this_driver_name, SPI_NAME_SIZE);
test_dev.spi_device = spi_device;
/* status = spi_add_device(spi_device);
if (status < 0)
{
spi_dev_put(spi_device);
printk(KERN_ALERT "spi_add_device() failed: %d\n",
status);
}
put_device(&spi_master->dev); */
printk(KERN_ALERT "@test_probe test_dev.spi_device: (%d)\n",&test_dev.spi_device);
up(&test_dev.spi_sem);
return 0;
}
static int test_remove(struct spi_device *spi_device)
{
if (down_interruptible(&test_dev.spi_sem))
return -EBUSY;
printk(KERN_ALERT "@test_remove\n");
test_dev.spi_device = NULL;
up(&test_dev.spi_sem);
return 0;
}
static struct spi_driver test_driver = {
.driver = {
.name = this_driver_name,
.owner = THIS_MODULE,
},
.probe = test_probe,
.remove = __devexit_p(test_remove),
};
static int __init test_init_spi(void)
{
int error;
printk(KERN_ALERT "@test_init_spi\n");
test_ctl.tx_buff = kmalloc(SPI_BUFF_SIZE, GFP_KERNEL | GFP_DMA);
if (!test_ctl.tx_buff) {
error = -ENOMEM;
goto test_init_error;
}
test_ctl.rx_buff = kmalloc(SPI_BUFF_SIZE, GFP_KERNEL | GFP_DMA);
if (!test_ctl.rx_buff) {
error = -ENOMEM;
goto test_init_error;
}
error = spi_register_driver(&test_driver);
if (error < 0) {
printk(KERN_ALERT "spi_register_driver() failed %d\n", error);
goto test_init_error;
}
return 0;
test_init_error:
if (test_ctl.tx_buff)
{
kfree(test_ctl.tx_buff);
test_ctl.tx_buff = 0;
}
if (test_ctl.rx_buff)
{
kfree(test_ctl.rx_buff);
test_ctl.rx_buff = 0;
}
return -1;
}
static const struct file_operations test_fops = {
.owner = THIS_MODULE,
.read = test_read,
.open = test_open,
};
static int __init test_init_cdev(void)
{
int error;
printk(KERN_ALERT "@test_init_cdev\n");
test_dev.devt = MKDEV(0, 0);
error = alloc_chrdev_region(&test_dev.devt, 0, 1, this_driver_name);
if (error < 0) {
printk(KERN_ALERT "alloc_chrdev_region() failed: %d \n",
error);
return -1;
}
cdev_init(&test_dev.cdev, &test_fops);
test_dev.cdev.owner = THIS_MODULE;
error = cdev_add(&test_dev.cdev, test_dev.devt, 1);
if (error) {
printk(KERN_ALERT "cdev_add() failed: %d\n", error);
unregister_chrdev_region(test_dev.devt, 1);
return -1;
}
return 0;
}
static int __init test_init_class(void)
{
printk(KERN_ALERT "@test_init_class\n");
test_dev.class = class_create(THIS_MODULE, this_driver_name);
if (!test_dev.class) {
printk(KERN_ALERT "class_create() failed\n");
return -1;
}
if (!device_create(test_dev.class, NULL, test_dev.devt, NULL,
this_driver_name)) {
printk(KERN_ALERT "device_create(..., %s) failed\n",
this_driver_name);
class_destroy(test_dev.class);
return -1;
}
return 0;
}
static int __init test_init(void)
{
memset(&test_dev, 0, sizeof(test_dev));
memset(&test_ctl, 0, sizeof(test_ctl));
sema_init(&test_dev.spi_sem, 1);
sema_init(&test_dev.fop_sem, 1);
if (test_init_cdev() < 0)
goto fail_1;
if (test_init_class() < 0)
goto fail_2;
if (test_init_spi() < 0)
goto fail_3;
return 0;
fail_3:
device_destroy(test_dev.class, test_dev.devt);
class_destroy(test_dev.class);
fail_2:
cdev_del(&test_dev.cdev);
unregister_chrdev_region(test_dev.devt, 1);
fail_1:
return -1;
}
module_init(test_init);
static void __exit test_exit(void)
{
spi_unregister_device(test_dev.spi_device);
spi_unregister_driver(&test_driver);
device_destroy(test_dev.class, test_dev.devt);
class_destroy(test_dev.class);
cdev_del(&test_dev.cdev);
unregister_chrdev_region(test_dev.devt, 1);
if (test_ctl.tx_buff)
kfree(test_ctl.tx_buff);
if (test_ctl.rx_buff)
kfree(test_ctl.rx_buff);
if (test_dev.user_buff)
kfree(test_dev.user_buff);
}
module_exit(test_exit);
this is from my devkit8000_spi_board_info[
Code:
static struct spi_board_info devkit8000_spi_board_info[] __initdata = {
{
.modalias = "ads7846",
.bus_num = 2,
.chip_select = 0,
.max_speed_hz = 1500000,
.controller_data = &ads7846_mcspi_config,
.irq = OMAP_GPIO_IRQ(OMAP3_DEVKIT_TS_GPIO),
.platform_data = &ads7846_config,
},
{
.modalias = "test",
.bus_num = 1,
.chip_select = 1,
.max_speed_hz = 2500000, // 25MHz
.mode = SPI_MODE_0,
},
};
|