/* Protects cx18_cards_active */
DEFINE_SPINLOCK(cx18_cards_lock);
+/* Queue for deferrable IRQ handling work for all cx18 cards in system */
+struct workqueue_struct *cx18_work_queue;
+
/* add your revision and whatnot here */
static struct pci_device_id cx18_pci_tbl[] __devinitdata = {
{PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1 };
-static int mmio_ndelay[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1 };
static unsigned cardtype_c = 1;
static unsigned tuner_c = 1;
static unsigned radio_c = 1;
-static unsigned mmio_ndelay_c = 1;
static char pal[] = "--";
static char secam[] = "--";
static char ntsc[] = "-";
static int cx18_pci_latency = 1;
-int cx18_retry_mmio = 1;
+static int mmio_ndelay;
+static int retry_mmio = 1;
+
int cx18_debug;
module_param_array(tuner, int, &tuner_c, 0644);
module_param_array(radio, bool, &radio_c, 0644);
module_param_array(cardtype, int, &cardtype_c, 0644);
-module_param_array(mmio_ndelay, int, &mmio_ndelay_c, 0644);
module_param_string(pal, pal, sizeof(pal), 0644);
module_param_string(secam, secam, sizeof(secam), 0644);
module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
module_param_named(debug, cx18_debug, int, 0644);
-module_param_named(retry_mmio, cx18_retry_mmio, int, 0644);
+module_param(mmio_ndelay, int, 0644);
+module_param(retry_mmio, int, 0644);
module_param(cx18_pci_latency, int, 0644);
module_param(cx18_first_minor, int, 0644);
"Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n"
"\t\t\tDefault: Yes");
MODULE_PARM_DESC(retry_mmio,
- "Check and retry memory mapped IO accesses\n"
- "\t\t\tDefault: 1 [Yes]");
+ "(Deprecated) MMIO writes are now always checked and retried\n"
+ "\t\t\tEffectively: 1 [Yes]");
MODULE_PARM_DESC(mmio_ndelay,
- "Delay (ns) for each CX23418 memory mapped IO access.\n"
- "\t\t\tTry larger values that are close to a multiple of the\n"
- "\t\t\tPCI clock period, 30.3 ns, if your card doesn't work.\n"
- "\t\t\tDefault: " __stringify(CX18_DEFAULT_MMIO_NDELAY));
+ "(Deprecated) MMIO accesses are now never purposely delayed\n"
+ "\t\t\tEffectively: 0 ns");
MODULE_PARM_DESC(enc_mpg_buffers,
"Encoder MPG Buffers (in MB)\n"
"\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS));
/* Generic utility functions */
int cx18_msleep_timeout(unsigned int msecs, int intr)
{
- int timeout = msecs_to_jiffies(msecs);
+ long int timeout = msecs_to_jiffies(msecs);
int sig;
do {
cx->options.tuner = tuner[cx->num];
cx->options.radio = radio[cx->num];
- if (mmio_ndelay[cx->num] < 0)
- cx->options.mmio_ndelay = CX18_DEFAULT_MMIO_NDELAY;
- else
- cx->options.mmio_ndelay = mmio_ndelay[cx->num];
-
cx->std = cx18_parse_std(cx);
if (cx->options.cardtype == -1) {
CX18_INFO("Ignore card\n");
*/
static int __devinit cx18_init_struct1(struct cx18 *cx)
{
+ int i;
+
cx->base_addr = pci_resource_start(cx->dev, 0);
mutex_init(&cx->serialize_lock);
mutex_init(&cx->i2c_bus_lock[0]);
mutex_init(&cx->i2c_bus_lock[1]);
mutex_init(&cx->gpio_lock);
+ mutex_init(&cx->epu2apu_mb_lock);
+ mutex_init(&cx->epu2cpu_mb_lock);
spin_lock_init(&cx->lock);
- spin_lock_init(&cx->dma_reg_lock);
+
+ for (i = 0; i < CX18_MAX_EPU_WORK_ORDERS; i++) {
+ cx->epu_work_order[i].cx = cx;
+ cx->epu_work_order[i].str = cx->epu_debug_str;
+ INIT_WORK(&cx->epu_work_order[i].work, cx18_epu_work_handler);
+ }
/* start counting open_id at 1 */
cx->open_id = 1;
init_waitqueue_head(&cx->cap_w);
init_waitqueue_head(&cx->mb_apu_waitq);
init_waitqueue_head(&cx->mb_cpu_waitq);
- init_waitqueue_head(&cx->mb_epu_waitq);
- init_waitqueue_head(&cx->mb_hpu_waitq);
init_waitqueue_head(&cx->dma_waitq);
/* VBI */
#ifdef MODULE
/* load modules */
-#ifndef CONFIG_MEDIA_TUNER
+#ifdef CONFIG_MEDIA_TUNER_MODULE
hw = cx18_request_module(cx, hw, "tuner", CX18_HW_TUNER);
#endif
-#ifndef CONFIG_VIDEO_CS5345
+#ifdef CONFIG_VIDEO_CS5345_MODULE
hw = cx18_request_module(cx, hw, "cs5345", CX18_HW_CS5345);
#endif
#endif
cx->std = V4L2_STD_NTSC_M;
if (cx->options.tuner == -1) {
- int i;
-
for (i = 0; i < CX18_CARD_MAX_TUNERS; i++) {
if ((cx->std & cx->card->tuners[i].std) == 0)
continue;
if (retval == 0)
retval = -ENODEV;
CX18_ERR("Error %d on initialization\n", retval);
- cx18_log_statistics(cx);
i = cx->num;
spin_lock(&cx18_cards_lock);
return 0;
}
+static void cx18_cancel_epu_work_orders(struct cx18 *cx)
+{
+ int i;
+ for (i = 0; i < CX18_MAX_EPU_WORK_ORDERS; i++)
+ cancel_work_sync(&cx->epu_work_order[i].work);
+}
+
static void cx18_remove(struct pci_dev *pci_dev)
{
struct cx18 *cx = pci_get_drvdata(pci_dev);
cx18_halt_firmware(cx);
+ cx18_cancel_epu_work_orders(cx);
+
cx18_streams_cleanup(cx, 1);
exit_cx18_i2c(cx);
pci_disable_device(cx->dev);
- cx18_log_statistics(cx);
CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num);
}
printk(KERN_INFO "cx18: Debug value must be >= 0 and <= 511!\n");
}
+ cx18_work_queue = create_singlethread_workqueue("cx18");
+ if (cx18_work_queue == NULL) {
+ printk(KERN_ERR
+ "cx18: Unable to create work hander thread\n");
+ return -ENOMEM;
+ }
+
if (pci_register_driver(&cx18_pci_driver)) {
printk(KERN_ERR "cx18: Error detecting PCI card\n");
+ destroy_workqueue(cx18_work_queue);
+ cx18_work_queue = NULL;
return -ENODEV;
}
printk(KERN_INFO "cx18: End initialization\n");
pci_unregister_driver(&cx18_pci_driver);
+ destroy_workqueue(cx18_work_queue);
+ cx18_work_queue = NULL;
+
for (i = 0; i < cx18_cards_active; i++) {
if (cx18_cards[i] == NULL)
continue;
kfree(cx18_cards[i]);
}
+
}
module_init(module_start);