[Linux1394-cvslog] rev 748 - trunk
Brought to you by:
aeb,
bencollins
From: SVN U. <dm...@li...> - 2003-02-01 14:00:00
|
Author: dmaas Date: 2003-01-15 04:44:57 -0500 (Wed, 15 Jan 2003) New Revision: 748 Modified: trunk/hosts.c trunk/hosts.h trunk/ohci1394.c trunk/ohci1394.h Log: ohci1394 - allocate legacy IT context on-demand also I had problems with legacy IT DMA before, so consider this change "lightly tested". Also cleaned up some comments in various places that incorrectly implied that they only apply to async DMA. Modified: trunk/ohci1394.c ============================================================================== --- trunk/ohci1394.c (original) +++ trunk/ohci1394.c 2003-02-01 08:59:28.000000000 -0500 @@ -175,6 +175,10 @@ int buf_size, int split_buf_size, int context_base); static void free_dma_rcv_ctx(struct dma_rcv_ctx *d); +static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d, + enum context_type type, int ctx, int num_desc, + int context_base); + static void ohci1394_pci_remove(struct pci_dev *pdev); #ifndef __LITTLE_ENDIAN @@ -462,6 +466,11 @@ INIT_LIST_HEAD(&d->fifo_list); INIT_LIST_HEAD(&d->pending_list); + if(d->type == DMA_CTX_ISO) { + /* enable interrupts */ + reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << d->ctx); + } + DBGMSG(ohci->id, "Transmit DMA ctx=%d initialized", d->ctx); } @@ -554,12 +563,6 @@ initialize_dma_trm_ctx(&ohci->at_req_context); initialize_dma_trm_ctx(&ohci->at_resp_context); - /* Initialize IT dma */ - initialize_dma_trm_ctx(&ohci->it_context); - - /* Set up isoXmitIntMask to generate interrupts for context 0 */ - reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 0x00000001); - /* * Accept AT requests from all nodes. This probably * will have to be controlled from the subsystem @@ -604,7 +607,7 @@ } /* - * Insert a packet in the AT DMA fifo and generate the DMA prg + * Insert a packet in the DMA fifo and generate the DMA prg * FIXME: rewrite the program in order to accept packets crossing * page boundaries. * check also that a single dma descriptor doesn't cross a @@ -763,8 +766,8 @@ } /* - * This function fills the AT FIFO with the (eventual) pending packets - * and runs or wakes up the AT DMA prg if necessary. + * This function fills the FIFO with the (eventual) pending packets + * and runs or wakes up the DMA prg if necessary. * * The function MUST be called with the d->lock held. */ @@ -780,7 +783,7 @@ idx = d->prg_ind; z = (p->data_size) ? 3 : 2; - /* insert the packets into the at dma fifo */ + /* insert the packets into the dma fifo */ while (d->free_prgs > 0 && !list_empty(&d->pending_list)) { struct hpsb_packet *p = driver_packet(d->pending_list.next); list_del(&p->driver_list); @@ -802,13 +805,15 @@ /* Wake up the dma context if necessary */ if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { DBGMSG(ohci->id,"Waking transmit DMA ctx=%d",d->ctx); - reg_write(ohci, d->ctrlSet, 0x1000); } + + /* do this always, to avoid race condition */ + reg_write(ohci, d->ctrlSet, 0x1000); } return 1; } -/* Transmission of an async packet */ +/* Transmission of an async or iso packet */ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet) { struct ti_ohci *ohci = host->hostdata; @@ -825,9 +830,33 @@ /* Decide wether we have an iso, a request, or a response packet */ if (packet->type == hpsb_raw) d = &ohci->at_req_context; - else if (packet->tcode == TCODE_ISO_DATA) - d = &ohci->it_context; - else if (packet->tcode & 0x02) + else if (packet->tcode == TCODE_ISO_DATA) { + /* The legacy IT DMA context is initialized on first + * use. However, the alloc cannot be run from + * interrupt context, so we bail out if that is the + * case. I don't see anyone sending ISO packets from + * interrupt context anyway... */ + + if(ohci->it_legacy_context.ohci == NULL) { + if(in_interrupt()) { + PRINT(KERN_ERR, ohci->id, + "legacy IT context cannot be initialized during interrupt"); + return 0; + } + + if (alloc_dma_trm_ctx(ohci, &ohci->it_legacy_context, + DMA_CTX_ISO, 0, IT_NUM_DESC, + OHCI1394_IsoXmitContextBase) < 0) { + PRINT(KERN_ERR, ohci->id, + "error initializing legacy IT context"); + return 0; + } + + initialize_dma_trm_ctx(&ohci->it_legacy_context); + } + + d = &ohci->it_legacy_context; + } else if (packet->tcode & 0x02) d = &ohci->at_resp_context; else d = &ohci->at_req_context; @@ -970,7 +999,7 @@ } /* activate the legacy IR context */ - if(!ohci->ir_legacy_active) { + if(ohci->ir_legacy_context.ohci == NULL) { if(alloc_dma_rcv_ctx(ohci, &ohci->ir_legacy_context, DMA_CTX_ISO, 0, IR_NUM_DESC, IR_BUF_SIZE, IR_SPLIT_BUF_SIZE, @@ -980,7 +1009,6 @@ __FUNCTION__); return -ENOMEM; } - ohci->ir_legacy_active = 1; ohci->ir_legacy_channels = 0; initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1); @@ -1037,10 +1065,9 @@ spin_unlock_irqrestore(&ohci->IR_channel_lock, flags); DBGMSG(ohci->id, "Listening disabled on channel %d", arg); - if(ohci->ir_legacy_channels == 0 && ohci->ir_legacy_active) { + if(ohci->ir_legacy_channels == 0) { free_dma_rcv_ctx(&ohci->ir_legacy_context); DBGMSG(ohci->id, "ISO receive legacy context deactivated"); - ohci->ir_legacy_active = 0; } break; } @@ -2912,12 +2939,18 @@ DBGMSG(d->ohci->id, "Freeing dma_trm_ctx %d", d->ctx); - ohci1394_stop_context(d->ohci, d->ctrlClear, NULL); + if(d->ctrlClear) { + ohci1394_stop_context(d->ohci, d->ctrlClear, NULL); - if (d->type == DMA_CTX_ISO) - ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->it_tasklet); - else - tasklet_kill(&d->task); + if (d->type == DMA_CTX_ISO) { + /* disable interrupts */ + reg_write(d->ohci, OHCI1394_IsoXmitIntMaskClear, 1 << d->ctx); + ohci1394_unregister_iso_tasklet(d->ohci, + &d->ohci->it_legacy_tasklet); + } else { + tasklet_kill(&d->task); + } + } if (d->prg_cpu) { for (i=0; i<d->num_desc; i++) @@ -2946,9 +2979,9 @@ d->type = type; d->ctx = ctx; d->num_desc = num_desc; - d->ctrlSet = context_base + OHCI1394_ContextControlSet; - d->ctrlClear = context_base + OHCI1394_ContextControlClear; - d->cmdPtr = context_base + OHCI1394_ContextCommandPtr; + d->ctrlSet = 0; + d->ctrlClear = 0; + d->cmdPtr = 0; d->prg_cpu = kmalloc(d->num_desc * sizeof(struct at_dma_prg*), GFP_KERNEL); @@ -2984,17 +3017,26 @@ /* initialize tasklet */ if (type == DMA_CTX_ISO) { - ohci1394_init_iso_tasklet(&ohci->it_tasklet, OHCI_ISO_TRANSMIT, + ohci1394_init_iso_tasklet(&ohci->it_legacy_tasklet, OHCI_ISO_TRANSMIT, dma_trm_tasklet, (unsigned long) d); if (ohci1394_register_iso_tasklet(ohci, - &ohci->it_tasklet) < 0) { + &ohci->it_legacy_tasklet) < 0) { PRINT(KERN_ERR, ohci->id, "No IT DMA context available"); free_dma_trm_ctx(d); return -EBUSY; } - } - else + + /* IT can be assigned to any context by register_iso_tasklet */ + d->ctx = ohci->it_legacy_tasklet.context; + d->ctrlSet = OHCI1394_IsoXmitContextControlSet + 16 * d->ctx; + d->ctrlClear = OHCI1394_IsoXmitContextControlClear + 16 * d->ctx; + d->cmdPtr = OHCI1394_IsoXmitCommandPtr + 16 * d->ctx; + } else { + d->ctrlSet = context_base + OHCI1394_ContextControlSet; + d->ctrlClear = context_base + OHCI1394_ContextControlClear; + d->cmdPtr = context_base + OHCI1394_ContextCommandPtr; tasklet_init (&d->task, dma_trm_tasklet, (unsigned long)d); + } return 0; } @@ -3348,14 +3390,11 @@ ohci->ISO_channel_usage = 0; spin_lock_init(&ohci->IR_channel_lock); - /* the IR DMA context is allocated on-demand */ - ohci->ir_legacy_active = 0; + /* the IR DMA context is allocated on-demand; mark it inactive */ + ohci->ir_legacy_context.ohci = NULL; - /* IT DMA context allocation */ - if (alloc_dma_trm_ctx(ohci, &ohci->it_context, - DMA_CTX_ISO, 0, IT_NUM_DESC, - OHCI1394_IsoXmitContextBase) < 0) - FAIL(-ENOMEM, "Failed to allocate IT context"); + /* same for the IT DMA context */ + ohci->it_legacy_context.ohci = NULL; if (request_irq(dev->irq, ohci_irq_handler, SA_SHIRQ, OHCI1394_DRIVER_NAME, ohci)) @@ -3400,11 +3439,10 @@ free_dma_trm_ctx(&ohci->at_resp_context); /* Free IR dma */ - if(ohci->ir_legacy_active) - free_dma_rcv_ctx(&ohci->ir_legacy_context); - + free_dma_rcv_ctx(&ohci->ir_legacy_context); + /* Free IT dma */ - free_dma_trm_ctx(&ohci->it_context); + free_dma_trm_ctx(&ohci->it_legacy_context); case OHCI_INIT_HAVE_SELFID_BUFFER: pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE, Modified: trunk/ohci1394.h ============================================================================== --- trunk/ohci1394.h (original) +++ trunk/ohci1394.h 2003-02-01 08:59:28.000000000 -0500 @@ -195,7 +195,6 @@ spinlock_t IR_channel_lock; /* iso receive (legacy API) */ - int ir_legacy_active; u64 ir_legacy_channels; /* note: this differs from ISO_channel_usage; it only accounts for channels listened to by the legacy API, so that we can know when @@ -205,11 +204,13 @@ struct ohci1394_iso_tasklet ir_legacy_tasklet; /* iso transmit */ - struct dma_trm_ctx it_context; - struct ohci1394_iso_tasklet it_tasklet; int nb_iso_xmit_ctx; unsigned long it_ctx_usage; /* use test_and_set_bit() for atomicity */ + /* iso transmit (legacy API) */ + struct dma_trm_ctx it_legacy_context; + struct ohci1394_iso_tasklet it_legacy_tasklet; + u64 ISO_channel_usage; /* IEEE-1394 part follows */ Modified: trunk/hosts.c ============================================================================== --- trunk/hosts.c (original) +++ trunk/hosts.c 2003-02-01 08:59:28.000000000 -0500 @@ -38,9 +38,15 @@ return -1; } +static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg) +{ + return -1; +} + static struct hpsb_host_driver dummy_driver = { .transmit_packet = dummy_transmit_packet, - .devctl = dummy_devctl + .devctl = dummy_devctl, + .isoctl = dummy_isoctl }; /** Modified: trunk/hosts.h ============================================================================== --- trunk/hosts.h (original) +++ trunk/hosts.h 2003-02-01 08:59:28.000000000 -0500 @@ -173,8 +173,9 @@ */ int (*devctl) (struct hpsb_host *host, enum devctl_cmd command, int arg); - /* ISO transmission/reception functions. Return 0 on success, -1 on failure. - * If the low-level driver does not support the new ISO API, set isoctl to NULL. + /* ISO transmission/reception functions. Return 0 on success, -1 + * (or -EXXX errno code) on failure. If the low-level driver does not + * support the new ISO API, set isoctl to NULL. */ int (*isoctl) (struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg); |