aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/sep/sep_driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/sep/sep_driver.c')
-rw-r--r--drivers/staging/sep/sep_driver.c428
1 files changed, 318 insertions, 110 deletions
diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c
index 85d02c92aa7..a18bcb833e8 100644
--- a/drivers/staging/sep/sep_driver.c
+++ b/drivers/staging/sep/sep_driver.c
@@ -3846,16 +3846,68 @@ static irqreturn_t sep_inthandler(int irq, void *dev_id)
#endif
/*
+ Function that is called by rar_register when it is ready with
+ a region (only for Moorestown)
+ @sep_context_pointer: pointer to struct sep_device
+*/
+static int sep_callback(unsigned long sep_context_pointer)
+{
+ int error = 0;
+ struct sep_device *sep =
+ (struct sep_device *)sep_context_pointer;
+
+ dma_addr_t rar_end_address = 0;
+
+ dev_dbg(&sep->pdev->dev, "callback start\n");
+
+ error = rar_get_address(RAR_TYPE_IMAGE, &sep->rar_bus,
+ &rar_end_address);
+
+ if (error) {
+ dev_warn(&sep->pdev->dev, "mrst cant get rar region\n");
+ goto end_function;
+ }
+
+ sep->rar_size = (size_t)(rar_end_address - sep->rar_bus + 1);
+
+ if (!request_mem_region(sep->rar_bus, sep->rar_size,
+ "sep_sec_driver")) {
+ dev_warn(&sep->pdev->dev,
+ "request mem region for mrst failed\n");
+ error = -1;
+ goto end_function;
+ }
+
+ sep->rar_addr = ioremap_nocache(sep->rar_bus, sep->rar_size);
+ if (!sep->rar_addr) {
+ dev_warn(&sep->pdev->dev,
+ "ioremap nocache for mrst rar failed\n");
+ error = -1;
+ goto end_function;
+ }
+
+ dev_dbg(&sep->pdev->dev, "rar start is %p, phy is %p,"
+ " size is %x\n", sep->rar_addr, (void *)sep->rar_bus,
+ sep->rar_size);
+
+ sep->probed = 1;
+
+end_function:
+
+ dev_dbg(&sep->pdev->dev, "callback end\n");
+ return error;
+}
+
+/*
Function that is activated on the successful probe of the SEP device
*/
-static int __devinit sep_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int __devinit sep_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
int error = 0;
struct sep_device *sep;
- int counter;
- int size; /* size of memory for allocation */
- edbg("Sep pci probe starting\n");
+ pr_debug("Sep pci probe starting\n");
if (sep_dev != NULL) {
dev_warn(&pdev->dev, "only one SEP supported.\n");
return -EBUSY;
@@ -3864,89 +3916,122 @@ static int __devinit sep_probe(struct pci_dev *pdev, const struct pci_device_id
/* enable the device */
error = pci_enable_device(pdev);
if (error) {
- edbg("error enabling pci device\n");
+ dev_warn(&pdev->dev, "error enabling pci device\n");
goto end_function;
}
+ /* zero out sep structure */
+ memset((void *)&sep_instance, 0, sizeof(sep_instance));
+
/* set the pci dev pointer */
sep_dev = &sep_instance;
sep = &sep_instance;
- edbg("sep->shared_addr = %p\n", sep->shared_addr);
- /* transaction counter that coordinates the transactions between SEP
- and HOST */
- sep->send_ct = 0;
- /* counter for the messages from sep */
- sep->reply_ct = 0;
- /* counter for the number of bytes allocated in the pool
- for the current transaction */
- sep->data_pool_bytes_allocated = 0;
+ sep->pdev = pdev;
- /* calculate the total size for allocation */
- size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
- SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES + SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES + SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
+ if (pdev->device == MRST_PCI_DEVICE_ID)
+ sep->mrst = 1;
+ else
+ sep->mrst = 0;
- /* allocate the shared area */
- if (sep_map_and_alloc_shared_area(sep, size)) {
- error = -ENOMEM;
- /* allocation failed */
- goto end_function_error;
- }
- /* now set the memory regions */
-#if (SEP_DRIVER_RECONFIG_MESSAGE_AREA == 1)
- /* Note: this test section will need moving before it could ever
- work as the registers are not yet mapped ! */
- /* send the new SHARED MESSAGE AREA to the SEP */
- sep_write_reg(sep, HW_HOST_HOST_SEP_GPR1_REG_ADDR, sep->shared_bus);
-
- /* poll for SEP response */
- retval = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR1_REG_ADDR);
- while (retval != 0xffffffff && retval != sep->shared_bus)
- retval = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR1_REG_ADDR);
-
- /* check the return value (register) */
- if (retval != sep->shared_bus) {
- error = -ENOMEM;
- goto end_function_deallocate_sep_shared_area;
+ dev_dbg(&sep->pdev->dev, "PCI obtained, device being prepared\n");
+
+#if !defined(CONFIG_RAR_REGISTER) || !defined(CONFIG_MRST_RAR_HANDLER)
+ if (sep->mrst) {
+ dev_warn(&sep->pdev->dev,
+ "You cannot have mrst and not have rar\n");
+ dev_warn(&sep->pdev->dev,
+ "Please configure the rar register and\n");
+ dev_warn(&sep->pdev->dev,
+ "ar handler and then recompile this kernel\n");
+ sep->probed = 0;
+ return -ENODEV;
}
#endif
- /* init the flow contextes */
- for (counter = 0; counter < SEP_DRIVER_NUM_FLOWS; counter++)
- sep->flows[counter].flow_id = SEP_FREE_FLOW_ID;
- sep->flow_wq = create_singlethread_workqueue("sepflowwq");
- if (sep->flow_wq == NULL) {
- error = -ENOMEM;
- edbg("sep_driver:flow queue creation failed\n");
- goto end_function_deallocate_sep_shared_area;
+ /* set up our register area */
+ sep->reg_physical_addr = pci_resource_start(sep->pdev, 0);
+ if (!sep->reg_physical_addr) {
+ dev_warn(&sep->pdev->dev, "Error getting register start\n");
+ pci_dev_put(sep->pdev);
+ return -ENODEV;
}
- edbg("SEP Driver: create flow workqueue \n");
- sep->pdev = pci_dev_get(pdev);
- sep->reg_addr = pci_ioremap_bar(pdev, 0);
+ sep->reg_physical_end = pci_resource_end(sep->pdev, 0);
+ if (!sep->reg_physical_end) {
+ dev_warn(&sep->pdev->dev, "Error getting register end\n");
+ pci_dev_put(sep->pdev);
+ return -ENODEV;
+ }
+
+ sep->reg_addr = ioremap_nocache(sep->reg_physical_addr,
+ (size_t)(sep->reg_physical_end - sep->reg_physical_addr + 1));
if (!sep->reg_addr) {
- edbg("sep: ioremap of registers failed.\n");
- goto end_function_deallocate_sep_shared_area;
+ dev_warn(&sep->pdev->dev, "Error getting register virtual\n");
+ pci_dev_put(sep->pdev);
+ return -ENODEV;
}
- edbg("SEP Driver:reg_addr is %p\n", sep->reg_addr);
- /* set up system base address and shared memory location */
- sep->rar_addr = dma_alloc_coherent(&sep->pdev->dev,
- 2 * SEP_RAR_IO_MEM_REGION_SIZE,
- &sep->rar_bus, GFP_KERNEL);
+ dev_dbg(&sep->pdev->dev,
+ "Register area start %p end %p virtual %p\n",
+ (void *)sep->reg_physical_addr,
+ (void *)sep->reg_physical_end,
+ sep->reg_addr);
- if (!sep->rar_addr) {
- edbg("SEP Driver:can't allocate rar\n");
- goto end_function_uniomap;
+ /* allocate the shared area */
+ sep->shared_size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
+ SYNCHRONIC_DMA_TABLES_AREA_SIZE_BYTES +
+ SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES +
+ SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES +
+ SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
+
+ if (sep_map_and_alloc_shared_area(sep)) {
+ error = -ENOMEM;
+ /* allocation failed */
+ goto end_function_error;
}
+ /* note that we will not set sep->probed at this time
+ because it cannot be set until after the callback
+ is called by the rar_register driver (for Moorestown)
+ is completed, which may end up being called after this
+ driver is finished probing because of order of compile
+ for the drivers in the kernel. Pleae note that attempts
+ to open this device while sep->probed is 0 will result
+ in -ENODEV error return */
- edbg("SEP Driver:rar_bus is %08llx\n", (unsigned long long)sep->rar_bus);
- edbg("SEP Driver:rar_virtual is %p\n", sep->rar_addr);
+ /* the next section depends on type of unit */
+ if (sep->mrst) {
+
+ error = register_rar(RAR_TYPE_IMAGE, &sep_callback,
+ (unsigned long)sejjp);
+ if (error) {
+ dev_dbg(&sep->pdev->dev,
+ "error register_rar\n");
+ goto end_function_deallocate_sep_shared_area;
+ }
+ }
+
+ else {
+
+ sep->rar_size = FAKE_RAR_SIZE;
+ sep->rar_addr = dma_alloc_coherent(NULL,
+ sep->rar_size, &sep->rar_bus, GFP_KERNEL);
+ if (sep->rar_addr == NULL) {
+ dev_warn(&sep->pdev->dev, "cant allocate mfld rar\n");
+ goto end_function_deallocate_sep_shared_area;
+ }
+
+ dev_dbg(&sep->pdev->dev, "rar start is %p, phy is %p,"
+ " size is %x\n", sep->rar_addr, (void *)sep->rar_bus,
+ sep->rar_size);
+ sep->probed = 1;
+ }
#if !SEP_DRIVER_POLLING_MODE
- edbg("SEP Driver: about to write IMR and ICR REG_ADDR\n");
+ dev_dbg(&sep->pdev->dev,
+ "about to write IMR and ICR REG_ADDR\n");
/* clear ICR register */
sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, 0xFFFFFFFF);
@@ -3954,13 +4039,17 @@ static int __devinit sep_probe(struct pci_dev *pdev, const struct pci_device_id
/* set the IMR register - open only GPR 2 */
sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, (~(0x1 << 13)));
- edbg("SEP Driver: about to call request_irq\n");
+ dev_dbg(&sep->pdev->dev,
+ "about to call request_irq\n");
/* get the interrupt line */
- error = request_irq(pdev->irq, sep_inthandler, IRQF_SHARED, "sep_driver", sep);
+ error = request_irq(pdev->irq, sep_inthandler, IRQF_SHARED,
+ "sep_driver", sep);
+
if (error)
goto end_function_free_res;
- return 0;
- edbg("SEP Driver: about to write IMR REG_ADDR");
+
+ dev_dbg(&sep->pdev->dev,
+ "about to write IMR REG_ADDR");
/* set the IMR register - open only GPR 2 */
sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, (~(0x1 << 13)));
@@ -3969,19 +4058,24 @@ end_function_free_res:
dma_free_coherent(&sep->pdev->dev, 2 * SEP_RAR_IO_MEM_REGION_SIZE,
sep->rar_addr, sep->rar_bus);
#endif /* SEP_DRIVER_POLLING_MODE */
-end_function_uniomap:
- iounmap(sep->reg_addr);
+
+goto end_function;
+
end_function_deallocate_sep_shared_area:
/* de-allocate shared area */
- sep_unmap_and_free_shared_area(sep, size);
+ sep_unmap_and_free_shared_area(sep);
+
end_function_error:
+ iounmap(sep->reg_addr);
sep_dev = NULL;
+
end_function:
return error;
}
static const struct pci_device_id sep_pci_id_tbl[] = {
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080c)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MRST_PCI_DEVICE_ID)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MFLD_PCI_DEVICE_ID)},
{0}
};
@@ -3995,11 +4089,28 @@ static struct pci_driver sep_pci_driver = {
/* FIXME: remove handler */
};
-/* major and minor device numbers */
-static dev_t sep_devno;
+/* file operation for singleton sep operations */
+static const struct file_operations singleton_file_operations = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = sep_singleton_ioctl,
+ .poll = sep_poll,
+ .open = sep_singleton_open,
+ .release = sep_singleton_release,
+ .mmap = sep_mmap,
+};
+
+/* file operation for daemon operations */
+static const struct file_operations daemon_file_operations = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = sep_request_daemon_ioctl,
+ .poll = sep_request_daemon_poll,
+ .open = sep_request_daemon_open,
+ .release = sep_request_daemon_release,
+ .mmap = sep_request_daemon_mmap,
+};
/* the files operations structure of the driver */
-static struct file_operations sep_file_operations = {
+static const struct file_operations sep_file_operations = {
.owner = THIS_MODULE,
.unlocked_ioctl = sep_ioctl,
.poll = sep_poll,
@@ -4008,32 +4119,95 @@ static struct file_operations sep_file_operations = {
.mmap = sep_mmap,
};
-
-/* cdev struct of the driver */
-static struct cdev sep_cdev;
-
/*
this function registers the driver to the file system
*/
-static int sep_register_driver_to_fs(void)
+static int sep_register_driver_to_fs(struct sep_device *sep)
{
- int ret_val = alloc_chrdev_region(&sep_devno, 0, 1, "sep_sec_driver");
+ int ret_val;
+ int major;
+
+ if (sep->mrst)
+ ret_val = alloc_chrdev_region(&sep->sep_devno,
+ 0, 2, "sep_sec_driver");
+ else
+ ret_val = alloc_chrdev_region(&sep->sep_devno,
+ 0, 3, "sep_sec_driver");
+
if (ret_val) {
- edbg("sep: major number allocation failed, retval is %d\n",
- ret_val);
+ dev_warn(&sep->pdev->dev,
+ "sep - major number allocation failed, retval is %d\n",
+ ret_val);
return ret_val;
}
+
+ major = MAJOR(sep->sep_devno);
+
+ /* for the sep device itself */
/* init cdev */
- cdev_init(&sep_cdev, &sep_file_operations);
- sep_cdev.owner = THIS_MODULE;
+ cdev_init(&sep->sep_cdev, &sep_file_operations);
+ sep->sep_cdev.owner = THIS_MODULE;
/* register the driver with the kernel */
- ret_val = cdev_add(&sep_cdev, sep_devno, 1);
+ ret_val = cdev_add(&sep->sep_cdev, sep->sep_devno, 1);
+ if (ret_val) {
+ dev_warn(&sep->pdev->dev,
+ "sep - cdev_add failed, retval is %d\n", ret_val);
+ /* unregister dev numbers */
+ goto end_function_unregister_devnum;
+ }
+
+ /* for the sep daemon port */
+ major = MAJOR(sep->sep_devno);
+ sep->sep_daemon_devno = MKDEV(major, 2);
+ cdev_init(&sep->sep_daemon_cdev, &daemon_file_operations);
+
+ sep->sep_daemon_cdev.owner = THIS_MODULE;
+
+ ret_val = cdev_add(&sep->sep_daemon_cdev, sep->sep_daemon_devno, 1);
if (ret_val) {
- edbg("sep_driver:cdev_add failed, retval is %d\n", ret_val);
+ dev_warn(&sep->pdev->dev,
+ "sep daemon - cdev_add failed, retval is %d\n",
+ ret_val);
/* unregister dev numbers */
- unregister_chrdev_region(sep_devno, 1);
+ cdev_del(&sep->sep_cdev);
+ goto end_function_unregister_devnum;
}
+
+ major = MAJOR(sep->sep_devno);
+ sep->sep_singleton_devno = MKDEV(major, 1);
+ cdev_init(&sep->sep_singleton_cdev, &singleton_file_operations);
+
+ sep->sep_singleton_cdev.owner = THIS_MODULE;
+
+ if (sep->mrst == 0) {
+
+ ret_val = cdev_add(&sep->sep_singleton_cdev,
+ sep->sep_singleton_devno, 1);
+ if (ret_val) {
+ dev_warn(&sep->pdev->dev,
+ "sep singleton -"
+ " cdev_add failed, retval is %d\n",
+ ret_val);
+ /* unregister dev numbers */
+ cdev_del(&sep->sep_cdev);
+ cdev_del(&sep->sep_daemon_cdev);
+ goto end_function_unregister_devnum;
+ }
+
+ }
+
+ goto end_function;
+
+end_function_unregister_devnum:
+
+ if (sep->mrst)
+ unregister_chrdev_region(sep->sep_devno, 2);
+ else
+ unregister_chrdev_region(sep->sep_devno, 3);
+
+end_function:
+
return ret_val;
}
@@ -4044,27 +4218,47 @@ static int sep_register_driver_to_fs(void)
static int __init sep_init(void)
{
int ret_val = 0;
- dbg("SEP Driver:-------->Init start\n");
- /* FIXME: Probe can occur before we are ready to survive a probe */
+ struct sep_device *sep;
+
+ sep = &sep_instance;
+
+ pr_debug("Sep driver: Init start\n");
+
ret_val = pci_register_driver(&sep_pci_driver);
if (ret_val) {
- edbg("sep_driver:sep_driver_to_device failed, ret_val is %d\n", ret_val);
- goto end_function_unregister_from_fs;
+ pr_debug("sep_driver:sep_driver_to_device failed,"
+ " ret_val is %d\n", ret_val);
+ goto end_function;
}
+
+ init_waitqueue_head(&sep->event);
+ init_waitqueue_head(&sep->event_request_daemon);
+
+ if (sep->mrst == 0) {
+ ret_val = sep_init_caller_id(sep);
+ if (ret_val) {
+ dev_warn(&sep->pdev->dev,
+ "cant init caller id\n");
+ goto end_function_unregister_pci;
+ }
+
+ }
+
/* register driver to fs */
- ret_val = sep_register_driver_to_fs();
- if (ret_val)
+ ret_val = sep_register_driver_to_fs(sep);
+ if (ret_val) {
+ dev_warn(&sep->pdev->dev,
+ "error registering device to file\n");
goto end_function_unregister_pci;
+ }
+
goto end_function;
+
end_function_unregister_pci:
pci_unregister_driver(&sep_pci_driver);
-end_function_unregister_from_fs:
- /* unregister from fs */
- cdev_del(&sep_cdev);
- /* unregister dev numbers */
- unregister_chrdev_region(sep_devno, 1);
+
end_function:
- dbg("SEP Driver:<-------- Init end\n");
+ dev_dbg(&sep->pdev->dev, "Init end\n");
return ret_val;
}
@@ -4074,27 +4268,41 @@ end_function:
--------------------------------------------------------------*/
static void __exit sep_exit(void)
{
- int size;
+ struct sep_device *sep;
- dbg("SEP Driver:--------> Exit start\n");
+ sep = &sep_instance;
+ pr_debug("Exit start\n");
/* unregister from fs */
- cdev_del(&sep_cdev);
+ cdev_del(&sep->sep_cdev);
+ cdev_del(&sep->sep_singleton_cdev);
+ cdev_del(&sep->sep_daemon_cdev);
+
/* unregister dev numbers */
- unregister_chrdev_region(sep_devno, 1);
+ if (sep->mrst)
+ unregister_chrdev_region(sep->sep_devno, 2);
+ else
+ unregister_chrdev_region(sep->sep_devno, 3);
+
+ /* free the irq */
+ free_irq(sep->pdev->irq, sep);
+
+ /* unregister the driver */
+ pci_unregister_driver(&sep_pci_driver);
+
/* calculate the total size for de-allocation */
- size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
- SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES + SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES + SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
/* FIXME: We need to do this in the unload for the device */
/* free shared area */
if (sep_dev) {
- sep_unmap_and_free_shared_area(sep_dev, size);
- edbg("SEP Driver: free pages SEP SHARED AREA \n");
+ sep_unmap_and_free_shared_area(sep_dev);
+ dev_dbg(&sep->pdev->dev,
+ "free pages SEP SHARED AREA\n");
iounmap((void *) sep_dev->reg_addr);
- edbg("SEP Driver: iounmap \n");
+ dev_dbg(&sep->pdev->dev,
+ "iounmap\n");
}
- edbg("SEP Driver: release_mem_region \n");
- dbg("SEP Driver:<-------- Exit end\n");
+ pr_debug("release_mem_region\n");
+ pr_debug("Exit end\n");
}