linux1394-cvslog Mailing List for IEEE 1394 for Linux (Page 5)
Brought to you by:
aeb,
bencollins
You can subscribe to this list here.
2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(10) |
Jul
(12) |
Aug
(8) |
Sep
(9) |
Oct
(4) |
Nov
(5) |
Dec
(5) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2001 |
Jan
(7) |
Feb
(3) |
Mar
(15) |
Apr
(12) |
May
(5) |
Jun
(9) |
Jul
(32) |
Aug
(39) |
Sep
(42) |
Oct
(22) |
Nov
(28) |
Dec
(8) |
2002 |
Jan
(37) |
Feb
(47) |
Mar
(6) |
Apr
(29) |
May
(33) |
Jun
(9) |
Jul
(28) |
Aug
(30) |
Sep
(15) |
Oct
(75) |
Nov
(37) |
Dec
(31) |
2003 |
Jan
|
Feb
(89) |
Mar
(41) |
Apr
(13) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: SVN U. <ben...@li...> - 2003-02-01 14:23:37
|
Author: bencollins Date: 2003-01-23 18:17:53 -0500 (Thu, 23 Jan 2003) New Revision: 753 Modified: branches/linux-2.4/Makefile Log: Revert back to original O_TARGET usage. Modified: branches/linux-2.4/Makefile ============================================================================== --- branches/linux-2.4/Makefile (original) +++ branches/linux-2.4/Makefile 2003-02-01 08:59:34.000000000 -0500 @@ -2,8 +2,11 @@ # Makefile for the Linux IEEE 1394 implementation # +O_TARGET := ieee1394drv.o + export-objs := ieee1394_core.o ohci1394.o cmp.o +list-multi := ieee1394.o ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \ highlevel.o csr.o nodemgr.o dma.o @@ -18,7 +21,7 @@ obj-$(CONFIG_IEEE1394_AMDTP) += amdtp.o obj-$(CONFIG_IEEE1394_CMP) += cmp.o +include $(TOPDIR)/Rules.make + ieee1394.o: $(ieee1394-objs) $(LD) $(LDFLAGS) -r -o $@ $(ieee1394-objs) - -include $(TOPDIR)/Rules.make |
From: SVN U. <dm...@li...> - 2003-02-01 14:23:35
|
Author: dmaas Date: 2003-01-15 10:36:43 -0500 (Wed, 15 Jan 2003) New Revision: 752 Modified: trunk/ohci1394.c Log: rawiso - implement packet-per-buffer mode as an option, and implement sync matching for receive Modified: trunk/ohci1394.c ============================================================================== --- trunk/ohci1394.c (original) +++ trunk/ohci1394.c 2003-02-01 08:59:33.000000000 -0500 @@ -1084,15 +1084,16 @@ ***********************************/ /* - We use buffer-fill DMA mode. The DMA buffer is split into "blocks" - of one page each. It would be fairly easy to make blocks smaller - than a page, but I think the latency is good enough already. + We use either buffer-fill or packet-per-buffer DMA mode. The DMA + buffer is split into "blocks" (regions described by one DMA + descriptor). Each block must be one page or less in size, and + must not cross a page boundary. There is one little wrinkle with buffer-fill mode: a packet that starts in the final block may wrap around into the first block. But the user API expects all packets to be contiguous. Our solution is to keep the very last page of the DMA buffer in reserve - if a - packet span the gap, we copy its tail into this page. + packet spans the gap, we copy its tail into this page. */ struct ohci_iso_recv { @@ -1101,93 +1102,122 @@ struct ohci1394_iso_tasklet task; int task_active; + enum { BUFFER_FILL_MODE, + PACKET_PER_BUFFER_MODE } dma_mode; + /* memory and PCI mapping for the DMA descriptors */ struct dma_prog_region prog; struct dma_cmd *block; /* = (struct dma_cmd*) prog.virt */ - /* how many INPUT_MORE blocks fit in the buffer */ + /* how many DMA blocks fit in the buffer */ unsigned int nblocks; + /* stride of DMA blocks */ + unsigned int buf_stride; + /* number of blocks to batch between interrupts */ int block_irq_interval; - /* block that the reader will release next */ + /* block that DMA will finish next */ + int block_dma; + + /* (buffer-fill only) block that the reader will release next */ int block_reader; - /* bytes of buffer the reader has released, less than one block */ + /* (buffer-fill only) bytes of buffer the reader has released, + less than one block */ int released_bytes; - /* the following four fields are used exclusively by the interrupt - (no locking is required) */ - - /* block that DMA will finish next */ - int block_dma; - - /* buffer offset at which the next packet will appear */ + /* (buffer-fill only) buffer offset at which the next packet will appear */ int dma_offset; - /* throttle the rate of buffer-space warnings to avoid - spamming the syslog */ - int warn_backoff; - /* OHCI DMA context control registers */ u32 ContextControlSet; u32 ContextControlClear; u32 CommandPtr; u32 ContextMatch; - }; -static void ohci_iso_recv_task(unsigned long data); +static void ohci_iso_recv_bufferfill_task(unsigned long data); +static void ohci_iso_recv_packetperbuf_task(unsigned long data); static void ohci_iso_recv_stop(struct hpsb_iso *iso); static void ohci_iso_recv_shutdown(struct hpsb_iso *iso); +static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync); static void ohci_iso_recv_program(struct hpsb_iso *iso); -static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask); - static int ohci_iso_recv_init(struct hpsb_iso *iso) { struct ti_ohci *ohci = iso->host->hostdata; struct ohci_iso_recv *recv; - unsigned int nblocks; int ctx; int ret = -ENOMEM; - /* one block per page of data in the DMA buffer, minus the final guard page */ - nblocks = iso->buf_size/PAGE_SIZE - 1; - if(nblocks < 3) { - DBGMSG(ohci->id, "ohci_iso_recv_init: DMA buffer too small"); - return -EINVAL; - } - recv = kmalloc(sizeof(*recv), SLAB_KERNEL); - if(!recv) { + if(!recv) return -ENOMEM; - } iso->hostdata = recv; recv->ohci = ohci; recv->task_active = 0; dma_prog_region_init(&recv->prog); recv->block = NULL; - recv->nblocks = nblocks; - /* iso->irq_interval is in packets - translate that to blocks */ - /* (err, sort of... 1 is always the safest value) */ - recv->block_irq_interval = iso->irq_interval / nblocks; - if(recv->block_irq_interval < 1) + /* use buffer-fill mode, unless irq_interval is 1 + (note: multichannel requires buffer-fill) */ + + if(iso->irq_interval == 1 && iso->channel != -1) { + recv->dma_mode = PACKET_PER_BUFFER_MODE; + } else { + recv->dma_mode = BUFFER_FILL_MODE; + } + + /* set nblocks, buf_stride, block_irq_interval */ + + if(recv->dma_mode == BUFFER_FILL_MODE) { + recv->buf_stride = PAGE_SIZE; + + /* one block per page of data in the DMA buffer, minus the final guard page */ + recv->nblocks = iso->buf_size/PAGE_SIZE - 1; + if(recv->nblocks < 3) { + DBGMSG(ohci->id, "ohci_iso_recv_init: DMA buffer too small"); + goto err; + } + + /* iso->irq_interval is in packets - translate that to blocks */ + /* (err, sort of... 1 is always the safest value) */ + recv->block_irq_interval = iso->irq_interval / recv->nblocks; + if(recv->block_irq_interval < 1) + recv->block_irq_interval = 1; + else if(recv->block_irq_interval*4 > recv->nblocks) + recv->block_irq_interval = recv->nblocks/4; + } else { + int max_packet_size; + + recv->nblocks = iso->buf_packets; recv->block_irq_interval = 1; - else if(recv->block_irq_interval*4 > recv->nblocks) - recv->block_irq_interval = nblocks/4; + + /* choose a buffer stride */ + /* must be a power of 2, and <= PAGE_SIZE */ + + max_packet_size = iso->buf_size / iso->buf_packets; + + for(recv->buf_stride = 8; recv->buf_stride < max_packet_size; + recv->buf_stride *= 2); + + if(recv->buf_stride*iso->buf_packets > iso->buf_size || + recv->buf_stride > PAGE_SIZE) { + /* this shouldn't happen, but anyway... */ + DBGMSG(ohci->id, "ohci_iso_recv_init: problem choosing a buffer stride"); + goto err; + } + } recv->block_reader = 0; recv->released_bytes = 0; - recv->block_dma = 0; - recv->dma_offset = recv->block_dma * PAGE_SIZE; - recv->warn_backoff = 0; + recv->dma_offset = 0; - /* size of DMA program = one INPUT_MORE per block */ + /* size of DMA program = one descriptor per block */ if(dma_prog_region_alloc(&recv->prog, sizeof(struct dma_cmd) * recv->nblocks, recv->ohci->dev)) @@ -1198,7 +1228,10 @@ ohci1394_init_iso_tasklet(&recv->task, iso->channel == -1 ? OHCI_ISO_MULTICHANNEL_RECEIVE : OHCI_ISO_RECEIVE, - ohci_iso_recv_task, (unsigned long) iso); + recv->dma_mode == BUFFER_FILL_MODE ? + ohci_iso_recv_bufferfill_task : + ohci_iso_recv_packetperbuf_task, + (unsigned long) iso); if(ohci1394_register_iso_tasklet(recv->ohci, &recv->task) < 0) goto err; @@ -1221,10 +1254,12 @@ /* write the DMA program */ ohci_iso_recv_program(iso); - DBGMSG(ohci->id, "ohci_iso_recv_init: DMA buffer is %lu pages" - " (%u bytes), using %u blocks, block_irq_interval %d", + DBGMSG(ohci->id, "ohci_iso_recv_init: %s mode, DMA buffer is %lu pages" + " (%u bytes), using %u blocks, buf_stride %u, block_irq_interval %d", + recv->dma_mode == BUFFER_FILL_MODE ? + "buffer-fill" : "packet-per-buffer", iso->buf_size/PAGE_SIZE, iso->buf_size, - recv->nblocks, recv->block_irq_interval); + recv->nblocks, recv->buf_stride, recv->block_irq_interval); return 0; @@ -1263,51 +1298,48 @@ static void ohci_iso_recv_program(struct hpsb_iso *iso) { struct ohci_iso_recv *recv = iso->hostdata; + int blk; /* address of 'branch' field in previous DMA descriptor */ u32 *prev_branch = NULL; - /* start at block_dma and go around the whole buffer */ - int blk = recv->block_dma; - int i; - - for(i = 0; i < recv->nblocks; i++) { + for(blk = 0; blk < recv->nblocks; blk++) { /* the DMA descriptor */ - struct dma_cmd *im = &recv->block[blk]; + struct dma_cmd *cmd = &recv->block[blk]; /* offset of the DMA descriptor relative to the DMA prog buffer */ unsigned long prog_offset = blk * sizeof(struct dma_cmd); /* offset of this packet's data within the DMA buffer */ - unsigned long buf_offset = blk*PAGE_SIZE; + unsigned long buf_offset = blk * recv->buf_stride; - unsigned short data_size = PAGE_SIZE; - - im->control = 2 << 28; /* INPUT_MORE */ - im->control |= 8 << 24; /* s = 1, update xferStatus and resCount */ + if(recv->dma_mode == BUFFER_FILL_MODE) { + cmd->control = 2 << 28; /* INPUT_MORE */ + } else { + cmd->control = 3 << 28; /* INPUT_LAST */ + } + + cmd->control |= 8 << 24; /* s = 1, update xferStatus and resCount */ /* interrupt on last block, and at intervals */ - if(i == recv->nblocks-1 || (i % recv->block_irq_interval) == 0) { - im->control |= 3 << 20; /* want interrupt */ + if(blk == recv->nblocks-1 || (blk % recv->block_irq_interval) == 0) { + cmd->control |= 3 << 20; /* want interrupt */ } - im->control |= 3 << 18; /* enable branch to address */ - im->control |= data_size; + cmd->control |= 3 << 18; /* enable branch to address */ + cmd->control |= recv->buf_stride; - im->address = dma_region_offset_to_bus(&iso->data_buf, buf_offset); - im->branchAddress = 0; /* filled in on next loop */ - im->status = data_size; + cmd->address = dma_region_offset_to_bus(&iso->data_buf, buf_offset); + cmd->branchAddress = 0; /* filled in on next loop */ + cmd->status = recv->buf_stride; /* link the previous descriptor to this one */ if(prev_branch) { - *prev_branch = dma_prog_region_offset_to_bus(&recv->prog, - prog_offset); + *prev_branch = dma_prog_region_offset_to_bus(&recv->prog, prog_offset); *prev_branch |= 1; /* set Z=1 */ } - prev_branch = &im->branchAddress; - - blk = (blk + 1) % recv->nblocks; + prev_branch = &cmd->branchAddress; } /* the final descriptor's branch address and Z should be left at 0 */ @@ -1358,7 +1390,7 @@ reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer); } -static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask) +static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync) { struct ohci_iso_recv *recv = iso->hostdata; u32 command, contextMatch; @@ -1366,8 +1398,13 @@ reg_write(recv->ohci, recv->ContextControlClear, 0xFFFFFFFF); wmb(); - /* use buffer-fill mode, and keep ISO headers (required for multichannel) */ - reg_write(recv->ohci, recv->ContextControlSet, (1 << 31) | (1 << 30)); + /* always keep ISO headers */ + command = (1 << 30); + + if(recv->dma_mode == BUFFER_FILL_MODE) + command |= (1 << 31); + + reg_write(recv->ohci, recv->ContextControlSet, command); /* match on specified tags */ contextMatch = tag_mask << 28; @@ -1401,6 +1438,15 @@ contextMatch |= cycle << 12; } + if(sync != -1) { + /* set sync flag on first DMA descriptor */ + struct dma_cmd *cmd = &recv->block[recv->block_dma]; + cmd->control |= DMA_CTL_WAIT; + + /* match sync field */ + contextMatch |= (sync&0xf)<<8; + } + reg_write(recv->ohci, recv->ContextMatch, contextMatch); /* address of first descriptor block */ @@ -1434,42 +1480,22 @@ return 0; } -static void ohci_iso_recv_check_block_overflow(struct ohci_iso_recv *recv) -{ - /* see how close we are to running out of blocks */ - int gap = 0; - int blk = recv->block_reader; - while(blk != recv->block_dma) { - blk = (blk+1) % recv->nblocks; - gap++; - } - - if(gap*2 > recv->nblocks) { - DBGMSG(recv->ohci->id, - "Running out of DMA blocks for ISO reception - " - "overrun likely (gap = %d)", gap); - } -} - -static void ohci_iso_recv_release_block(struct hpsb_iso *iso, struct ohci_iso_recv *recv) +static void ohci_iso_recv_release_block(struct ohci_iso_recv *recv, int block) { - /* re-use the DMA descriptor for block_reader */ + /* re-use the DMA descriptor for the block */ /* by linking the previous descriptor to it */ - int next_i = recv->block_reader; + int next_i = block; int prev_i = (next_i == 0) ? (recv->nblocks - 1) : (next_i - 1); struct dma_cmd *next = &recv->block[next_i]; struct dma_cmd *prev = &recv->block[prev_i]; - ohci_iso_recv_check_block_overflow(recv); - /* 'next' becomes the new end of the DMA chain, so disable branch and enable interrupt */ - next->branchAddress = 0; next->control |= 3 << 20; - + /* link prev to next */ prev->branchAddress = dma_prog_region_offset_to_bus(&recv->prog, sizeof(struct dma_cmd) * next_i) @@ -1485,14 +1511,11 @@ /* wake up DMA in case it fell asleep */ reg_write(recv->ohci, recv->ContextControlSet, (1 << 12)); - - /* advance block cursor */ - recv->block_reader = (recv->block_reader + 1) % recv->nblocks; } -static void ohci_iso_recv_release(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info) +static void ohci_iso_recv_bufferfill_release(struct ohci_iso_recv *recv, + struct hpsb_iso_packet_info *info) { - struct ohci_iso_recv *recv = iso->hostdata; int len; /* release the memory where the packet was */ @@ -1508,14 +1531,25 @@ recv->released_bytes += len; /* have we released enough memory for one block? */ - while(recv->released_bytes > PAGE_SIZE) { - ohci_iso_recv_release_block(iso, recv); - recv->released_bytes -= PAGE_SIZE; + while(recv->released_bytes > recv->buf_stride) { + ohci_iso_recv_release_block(recv, recv->block_reader); + recv->block_reader = (recv->block_reader + 1) % recv->nblocks; + recv->released_bytes -= recv->buf_stride; + } +} + +static inline void ohci_iso_recv_release(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info) +{ + struct ohci_iso_recv *recv = iso->hostdata; + if(recv->dma_mode == BUFFER_FILL_MODE) { + ohci_iso_recv_bufferfill_release(recv, info); + } else { + ohci_iso_recv_release_block(recv, info - iso->infos); } } /* parse all packets from blocks that have been fully received */ -static void ohci_iso_recv_bytes(struct hpsb_iso *iso, struct ohci_iso_recv *recv) +static void ohci_iso_recv_bufferfill_parse(struct hpsb_iso *iso, struct ohci_iso_recv *recv) { int wake = 0; int runaway = 0; @@ -1530,7 +1564,7 @@ unsigned char *p = iso->data_buf.kvirt; - unsigned int this_block = recv->dma_offset/PAGE_SIZE; + unsigned int this_block = recv->dma_offset/recv->buf_stride; /* don't loop indefinitely */ if(runaway++ > 100000) { @@ -1553,7 +1587,7 @@ len = p[recv->dma_offset+2] | (p[recv->dma_offset+3] << 8); - if(len > PAGE_SIZE) { + if(len > 4096) { PRINT(KERN_ERR, recv->ohci->id, "IR DMA error - bogus 'len' value %u\n", len); } @@ -1566,8 +1600,8 @@ recv->dma_offset += 4; /* check for wrap-around */ - if(recv->dma_offset >= PAGE_SIZE*recv->nblocks) { - recv->dma_offset -= PAGE_SIZE*recv->nblocks; + if(recv->dma_offset >= recv->buf_stride*recv->nblocks) { + recv->dma_offset -= recv->buf_stride*recv->nblocks; } /* dma_offset now points to the first byte of the data payload */ @@ -1582,22 +1616,22 @@ } /* check for wrap-around */ - if(recv->dma_offset >= PAGE_SIZE*recv->nblocks) { + if(recv->dma_offset >= recv->buf_stride*recv->nblocks) { /* uh oh, the packet data wraps from the last to the first DMA block - make the packet contiguous by copying its "tail" into the guard page */ - int guard_off = recv->nblocks*PAGE_SIZE; + int guard_off = recv->buf_stride*recv->nblocks; int tail_len = len - (guard_off - offset); - if(tail_len > 0 && tail_len < PAGE_SIZE) { + if(tail_len > 0 && tail_len < recv->buf_stride) { memcpy(iso->data_buf.kvirt + guard_off, iso->data_buf.kvirt, tail_len); } - recv->dma_offset -= PAGE_SIZE*recv->nblocks; + recv->dma_offset -= recv->buf_stride*recv->nblocks; } /* parse timestamp */ @@ -1608,8 +1642,8 @@ recv->dma_offset += 4; /* check for wrap-around */ - if(recv->dma_offset >= PAGE_SIZE*recv->nblocks) { - recv->dma_offset -= PAGE_SIZE*recv->nblocks; + if(recv->dma_offset >= recv->buf_stride*recv->nblocks) { + recv->dma_offset -= recv->buf_stride*recv->nblocks; } hpsb_iso_packet_received(iso, offset, len, cycle, channel, tag, sy); @@ -1619,7 +1653,7 @@ hpsb_iso_wake(iso); } -static void ohci_iso_recv_task(unsigned long data) +static void ohci_iso_recv_bufferfill_task(unsigned long data) { struct hpsb_iso *iso = (struct hpsb_iso*) data; struct ohci_iso_recv *recv = iso->hostdata; @@ -1661,11 +1695,11 @@ /* OK, the block is finished... */ /* sync our view of the block */ - dma_region_sync(&iso->data_buf, recv->block_dma*PAGE_SIZE, PAGE_SIZE); + dma_region_sync(&iso->data_buf, recv->block_dma*recv->buf_stride, recv->buf_stride); /* reset the DMA descriptor */ - im->status = PAGE_SIZE; - + im->status = recv->buf_stride; + /* advance block_dma */ recv->block_dma = (recv->block_dma + 1) % recv->nblocks; @@ -1677,7 +1711,84 @@ } /* parse any packets that have arrived */ - ohci_iso_recv_bytes(iso, recv); + ohci_iso_recv_bufferfill_parse(iso, recv); +} + +static void ohci_iso_recv_packetperbuf_task(unsigned long data) +{ + struct hpsb_iso *iso = (struct hpsb_iso*) data; + struct ohci_iso_recv *recv = iso->hostdata; + int count; + int wake = 0; + + /* loop over the entire buffer */ + for(count = 0; count < recv->nblocks; count++) { + u32 packet_len = 0; + + /* pointer to the DMA descriptor */ + struct dma_cmd *il = ((struct dma_cmd*) recv->prog.kvirt) + iso->pkt_dma; + + /* check the DMA descriptor for new writes to xferStatus */ + u16 xferstatus = il->status >> 16; + u16 rescount = il->status & 0xFFFF; + + unsigned char event = xferstatus & 0x1F; + + if(!event) { + /* this packet hasn't come in yet; we are done for now */ + goto out; + } + + if(event == 0x11) { + /* packet received successfully! */ + + /* rescount is the number of bytes *remaining* in the packet buffer, + after the packet was written */ + packet_len = recv->buf_stride - rescount; + + } else if(event == 0x02) { + PRINT(KERN_ERR, recv->ohci->id, "IR DMA error - packet too long for buffer\n"); + } else if(event) { + PRINT(KERN_ERR, recv->ohci->id, "IR DMA error - OHCI error code 0x%02x\n", event); + } + + /* sync our view of the buffer */ + dma_region_sync(&iso->data_buf, iso->pkt_dma * recv->buf_stride, recv->buf_stride); + + /* record the per-packet info */ + { + /* iso header is 8 bytes ahead of the data payload */ + unsigned char *hdr; + + unsigned int offset; + unsigned short cycle; + unsigned char channel, tag, sy; + + offset = iso->pkt_dma * recv->buf_stride; + hdr = iso->data_buf.kvirt + offset; + + /* skip iso header */ + offset += 8; + packet_len -= 8; + + cycle = (hdr[0] | (hdr[1] << 8)) & 0x1FFF; + channel = hdr[5] & 0x3F; + tag = hdr[5] >> 6; + sy = hdr[4] & 0xF; + + hpsb_iso_packet_received(iso, offset, packet_len, cycle, channel, tag, sy); + } + + /* reset the DMA descriptor */ + il->status = recv->buf_stride; + + wake = 1; + recv->block_dma = iso->pkt_dma; + } + +out: + if(wake) + hpsb_iso_wake(iso); } @@ -1994,7 +2105,7 @@ return ohci_iso_recv_init(iso); case RECV_START: { int *args = (int*) arg; - return ohci_iso_recv_start(iso, args[0], args[1]); + return ohci_iso_recv_start(iso, args[0], args[1], args[2]); } case RECV_STOP: ohci_iso_recv_stop(iso); |
From: SVN U. <dm...@li...> - 2003-02-01 14:23:35
|
Author: dmaas Date: 2003-01-15 08:12:56 -0500 (Wed, 15 Jan 2003) New Revision: 751 Modified: trunk/raw1394.c trunk/raw1394.h Log: rename RAW1394_ISO_STOP to RAW1394_ISO_XMIT_RECV_STOP to avoid clash with user-space name Modified: trunk/raw1394.c ============================================================================== --- trunk/raw1394.c (original) +++ trunk/raw1394.c 2003-02-01 08:59:32.000000000 -0500 @@ -2255,7 +2255,7 @@ return -EFAULT; return hpsb_iso_recv_start(fi->iso_handle, args[0], args[1], args[2]); } - case RAW1394_ISO_STOP: + case RAW1394_ISO_XMIT_RECV_STOP: hpsb_iso_stop(fi->iso_handle); return 0; case RAW1394_ISO_RECV_LISTEN_CHANNEL: @@ -2294,7 +2294,7 @@ } case RAW1394_ISO_XMIT_SYNC: return hpsb_iso_xmit_sync(fi->iso_handle); - case RAW1394_ISO_STOP: + case RAW1394_ISO_XMIT_RECV_STOP: hpsb_iso_stop(fi->iso_handle); return 0; case RAW1394_ISO_GET_STATUS: Modified: trunk/raw1394.h ============================================================================== --- trunk/raw1394.h (original) +++ trunk/raw1394.h 2003-02-01 08:59:33.000000000 -0500 @@ -122,7 +122,7 @@ #define RAW1394_ISO_RECV_INIT 2 /* arg: raw1394_iso_status* */ #define RAW1394_ISO_RECV_START 3 /* arg: int[3], { starting cycle, tag, sync } */ #define RAW1394_ISO_XMIT_START 8 /* arg: int[2], { starting cycle, prebuffer } */ -#define RAW1394_ISO_STOP 4 +#define RAW1394_ISO_XMIT_RECV_STOP 4 #define RAW1394_ISO_GET_STATUS 5 /* arg: raw1394_iso_status* */ #define RAW1394_ISO_PRODUCE_CONSUME 6 /* no longer used */ #define RAW1394_ISO_SHUTDOWN 7 |
From: SVN U. <ben...@li...> - 2003-02-01 14:23:35
|
Author: bencollins Date: 2003-01-23 18:18:29 -0500 (Thu, 23 Jan 2003) New Revision: 754 Modified: branches/linux-2.4/sbp2.c Log: Remove duplicate blk.h include. This was a merge from 2.4.21-pre3. Modified: branches/linux-2.4/sbp2.c ============================================================================== --- branches/linux-2.4/sbp2.c (original) +++ branches/linux-2.4/sbp2.c 2003-02-01 08:59:35.000000000 -0500 @@ -320,7 +320,6 @@ #include <linux/blk.h> #include <linux/smp_lock.h> #include <linux/init.h> -#include <linux/blk.h> #include <asm/current.h> #include <asm/uaccess.h> #include <asm/io.h> |
From: SVN U. <ben...@li...> - 2003-02-01 14:23:35
|
Author: bencollins Date: 2003-01-23 18:51:24 -0500 (Thu, 23 Jan 2003) New Revision: 755 Removed: tags/linux-2.4-sync/ Log: Remove old 2.4 tag |
From: SVN U. <we...@li...> - 2003-02-01 14:23:34
|
Author: weihs Date: 2003-01-26 07:47:55 -0500 (Sun, 26 Jan 2003) New Revision: 758 Modified: branches/linux-2.4/ohci1394.c branches/linux-2.4/ohci1394.h Log: backported fix fro OHCI evt_* from trunk Modified: branches/linux-2.4/ohci1394.c ============================================================================== --- branches/linux-2.4/ohci1394.c (original) +++ branches/linux-2.4/ohci1394.c 2003-02-01 08:59:38.000000000 -0500 @@ -1439,7 +1439,7 @@ struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci); struct hpsb_packet *packet; unsigned long flags; - u32 ack; + u32 status, ack; size_t datasize; spin_lock_irqsave(&d->lock, flags); @@ -1448,25 +1448,16 @@ packet = driver_packet(d->fifo_list.next); datasize = packet->data_size; if (datasize && packet->type != hpsb_raw) - ack = le32_to_cpu( + status = le32_to_cpu( d->prg_cpu[d->sent_ind]->end.status) >> 16; else - ack = le32_to_cpu( + status = le32_to_cpu( d->prg_cpu[d->sent_ind]->begin.status) >> 16; - if (ack == 0) + if (status == 0) /* this packet hasn't been sent yet*/ break; - if (!(ack & 0x10)) { - /* XXX: This is an OHCI evt_* code. We need to handle - * this specially! For right now, we just fake an - * ackx_send_error. */ - PRINT(KERN_DEBUG, ohci->id, "Received OHCI evt_* error 0x%x", - ack & 0xf); - ack = (ack & 0xffe0) | ACK_BUSY_A; - } - #ifdef OHCI1394_DEBUG if (datasize) DBGMSG(ohci->id, @@ -1478,7 +1469,7 @@ >>4)&0xf, (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0]) >>10)&0x3f, - ack&0x1f, (ack>>5)&0x3, + status&0x1f, (status>>5)&0x3, le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3]) >>16, d->ctx); @@ -1492,13 +1483,64 @@ >>4)&0xf, (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0]) >>10)&0x3f, - ack&0x1f, (ack>>5)&0x3, + status&0x1f, (status>>5)&0x3, le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3]), d->ctx); #endif + if (status & 0x10) { + ack = status & 0xf; + } else { + switch (status & 0x1f) { + case EVT_NO_STATUS: /* that should never happen */ + case EVT_RESERVED_A: /* that should never happen */ + case EVT_LONG_PACKET: /* that should never happen */ + PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f); + ack = ACKX_SEND_ERROR; + break; + case EVT_MISSING_ACK: + ack = ACKX_TIMEOUT; + break; + case EVT_UNDERRUN: + ack = ACKX_SEND_ERROR; + break; + case EVT_OVERRUN: /* that should never happen */ + PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f); + ack = ACKX_SEND_ERROR; + break; + case EVT_DESCRIPTOR_READ: + case EVT_DATA_READ: + case EVT_DATA_WRITE: + ack = ACKX_SEND_ERROR; + break; + case EVT_BUS_RESET: /* that should never happen */ + PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f); + ack = ACKX_SEND_ERROR; + break; + case EVT_TIMEOUT: + ack = ACKX_TIMEOUT; + break; + case EVT_TCODE_ERR: + ack = ACKX_SEND_ERROR; + break; + case EVT_RESERVED_B: /* that should never happen */ + case EVT_RESERVED_C: /* that should never happen */ + PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f); + ack = ACKX_SEND_ERROR; + break; + case EVT_UNKNOWN: + case EVT_FLUSHED: + ack = ACKX_SEND_ERROR; + break; + default: + PRINT(KERN_ERR, ohci->id, "Unhandled OHCI evt_* error 0x%x", status & 0x1f); + ack = ACKX_SEND_ERROR; + BUG(); + } + } + list_del(&packet->driver_list); - hpsb_packet_sent(ohci->host, packet, ack & 0xf); + hpsb_packet_sent(ohci->host, packet, ack); if (datasize) { pci_unmap_single(ohci->dev, Modified: branches/linux-2.4/ohci1394.h ============================================================================== --- branches/linux-2.4/ohci1394.h (original) +++ branches/linux-2.4/ohci1394.h 2003-02-01 08:59:38.000000000 -0500 @@ -380,7 +380,7 @@ /* OHCI evt_* error types, table 3-2 of the OHCI 1.1 spec. */ #define EVT_NO_STATUS 0x0 /* No event status */ -#define EVT_RESERVED 0x1 /* Reserved, not used !!! */ +#define EVT_RESERVED_A 0x1 /* Reserved, not used !!! */ #define EVT_LONG_PACKET 0x2 /* The revc data was longer than the buf */ #define EVT_MISSING_ACK 0x3 /* A subaction gap was detected before an ack arrived, or recv'd ack had a parity error */ @@ -399,6 +399,17 @@ 16-bit host memory write */ #define EVT_BUS_RESET 0x9 /* Identifies a PHY packet in the recv buffer as being a synthesized bus reset packet */ +#define EVT_TIMEOUT 0xa /* Indicates that the asynchronous transmit response + packet expired and was not transmitted, or that an + IT DMA context experienced a skip processing overflow */ +#define EVT_TCODE_ERR 0xb /* A bad tCode is associated with this packet. + The packet was flushed */ +#define EVT_RESERVED_B 0xc /* Reserved, not used !!! */ +#define EVT_RESERVED_C 0xd /* Reserved, not used !!! */ +#define EVT_UNKNOWN 0xe /* An error condition has occurred that cannot be + represented by any other event codes defined herein. */ +#define EVT_FLUSHED 0xf /* Send by the link side of output FIFO when asynchronous + packets are being flushed due to a bus reset. */ #define OHCI1394_TCODE_PHY 0xE |
From: SVN U. <ben...@li...> - 2003-02-01 14:23:34
|
Author: bencollins Date: 2003-01-30 21:14:45 -0500 (Thu, 30 Jan 2003) New Revision: 759 Modified: trunk/dv1394-private.h trunk/dv1394.c Log: Merge devfs changes from 2.5.59 Modified: trunk/dv1394-private.h ============================================================================== --- trunk/dv1394-private.h (original) +++ trunk/dv1394-private.h 2003-02-01 08:59:39.000000000 -0500 @@ -583,8 +583,5 @@ #define CIP_N_PAL 1 #define CIP_D_PAL 16 -/* Base for our DevFS entries */ -#define DV1394_DEV_BASE "ieee1394/dv" - #endif /* _DV_1394_PRIVATE_H */ Modified: trunk/dv1394.c ============================================================================== --- trunk/dv1394.c (original) +++ trunk/dv1394.c 2003-02-01 08:59:39.000000000 -0500 @@ -175,6 +175,15 @@ static struct hpsb_highlevel *hl_handle; /* = NULL; */ +static LIST_HEAD(dv1394_devfs); +struct dv1394_devfs_entry { + struct list_head list; + devfs_handle_t devfs; + char name[32]; + struct dv1394_devfs_entry *parent; +}; +static spinlock_t dv1394_devfs_lock = SPIN_LOCK_UNLOCKED; + /* translate from a struct file* to the corresponding struct video_card* */ static inline struct video_card* file_to_video_card(struct file *file) @@ -2447,40 +2456,135 @@ /*** DEVFS HELPERS *********************************************************/ +struct dv1394_devfs_entry * +dv1394_devfs_find( char *name) +{ + struct list_head *lh; + struct dv1394_devfs_entry *p; + + spin_lock( &dv1394_devfs_lock); + if(!list_empty(&dv1394_devfs)) { + list_for_each(lh, &dv1394_devfs) { + p = list_entry(lh, struct dv1394_devfs_entry, list); + if(!strncmp(p->name, name, sizeof(p->name))) { + goto found; + } + } + } + p = NULL; + +found: + spin_unlock( &dv1394_devfs_lock); + return p; +} + #ifdef CONFIG_DEVFS_FS static int dv1394_devfs_add_entry(struct video_card *video) { - char buf[64]; - snprintf(buf, sizeof(buf), DV1394_DEV_BASE "/host%d/%s/%s", - (video->id>>2), - (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"), - (video->mode == MODE_RECEIVE ? "in" : "out")); + char buf[32]; + struct dv1394_devfs_entry *p; + struct dv1394_devfs_entry *parent; - video->devfs_handle = devfs_register(NULL, buf, DEVFS_FL_NONE, + p = kmalloc(sizeof(struct dv1394_devfs_entry), GFP_KERNEL); + if(!p) { + printk(KERN_ERR "dv1394: cannot allocate dv1394_devfs_entry\n"); + goto err; + } + memset(p, 0, sizeof(struct dv1394_devfs_entry)); + + snprintf(buf, sizeof(buf), "dv/host%d/%s", (video->id>>2), + (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL")); + + parent = dv1394_devfs_find(buf); + if (parent == NULL) { + printk(KERN_ERR "dv1394: unable to locate parent devfs of %s\n", buf); + goto err_free; + } + + video->devfs_handle = devfs_register( + parent->devfs, + (video->mode == MODE_RECEIVE ? "in" : "out"), + DEVFS_FL_NONE, IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394*16 + video->id, S_IFCHR | S_IRUGO | S_IWUGO, &dv1394_fops, (void*) video); + p->devfs = video->devfs_handle; + if (p->devfs == NULL) { + printk(KERN_ERR "dv1394: unable to create /dev/ieee1394/%s/%s\n", + parent->name, + (video->mode == MODE_RECEIVE ? "in" : "out")); + goto err_free; + } + + spin_lock( &dv1394_devfs_lock); + INIT_LIST_HEAD(&p->list); + list_add_tail(&p->list, &dv1394_devfs); + spin_unlock( &dv1394_devfs_lock); + return 0; + + err_free: + kfree(p); + err: + return -ENOMEM; } -static int dv1394_devfs_add_dir(char *name) +static int +dv1394_devfs_add_dir( char *name, + struct dv1394_devfs_entry *parent, + struct dv1394_devfs_entry **out) { - if (!devfs_mk_dir(NULL, name, NULL)) - printk(KERN_ERR "dv1394: unable to create /dev/%s\n", name); - return -ENOMEM; + struct dv1394_devfs_entry *p; + + p = kmalloc(sizeof(struct dv1394_devfs_entry), GFP_KERNEL); + if(!p) { + printk(KERN_ERR "dv1394: cannot allocate dv1394_devfs_entry\n"); + goto err; + } + memset(p, 0, sizeof(struct dv1394_devfs_entry)); + + if (parent == NULL) { + snprintf(p->name, sizeof(p->name), "%s", name); + p->devfs = devfs_mk_dir(ieee1394_devfs_handle, name, NULL); + } else { + snprintf(p->name, sizeof(p->name), "%s/%s", parent->name, name); + p->devfs = devfs_mk_dir(parent->devfs, name, NULL); + } + if (p->devfs == NULL) { + printk(KERN_ERR "dv1394: unable to create /dev/ieee1394/%s\n", p->name); + goto err_free; } + p->parent = parent; + if (out != NULL) *out = p; + + spin_lock( &dv1394_devfs_lock); + INIT_LIST_HEAD(&p->list); + list_add_tail(&p->list, &dv1394_devfs); + spin_unlock( &dv1394_devfs_lock); + return 0; + + err_free: + kfree(p); + err: + return -ENOMEM; } void dv1394_devfs_del( char *name) { - char s[64]; - sprintf(s, "ieee1394/%s", name); - devfs_find_and_unregister(NULL, s, 0, 0, 0, 0); + struct dv1394_devfs_entry *p = dv1394_devfs_find(name); + if (p != NULL) { + devfs_unregister(p->devfs); + + spin_lock( &dv1394_devfs_lock); + list_del(&p->list); + spin_unlock( &dv1394_devfs_lock); + kfree(p); + } } #endif /* CONFIG_DEVFS_FS */ @@ -2664,12 +2768,15 @@ #endif #ifdef CONFIG_DEVFS_FS - snprintf(buf, sizeof(buf), DV1394_DEV_BASE "/host%d", ohci->id); - dv1394_devfs_add_dir(buf); - snprintf(buf, sizeof(buf), DV1394_DEV_BASE "/host%d/NTSC", ohci->id); - dv1394_devfs_add_dir(buf); - snprintf(buf, sizeof(buf), DV1394_DEV_BASE "/host%d/PAL", ohci->id); - dv1394_devfs_add_dir(buf); +{ + struct dv1394_devfs_entry *devfs_entry = dv1394_devfs_find("dv"); + if (devfs_entry != NULL) { + snprintf(buf, sizeof(buf), "host%d", ohci->id); + dv1394_devfs_add_dir(buf, devfs_entry, &devfs_entry); + dv1394_devfs_add_dir("NTSC", devfs_entry, NULL); + dv1394_devfs_add_dir("PAL", devfs_entry, NULL); + } +} #endif dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE); @@ -2829,8 +2936,8 @@ } #ifdef CONFIG_DEVFS_FS - if (dv1394_devfs_add_dir(DV1394_DEV_BASE) < 0) { - printk(KERN_ERR "dv1394: unable to create /dev/%s\n", DV1394_DEV_BASE); + if (dv1394_devfs_add_dir("dv", NULL, NULL) < 0) { + printk(KERN_ERR "dv1394: unable to create /dev/ieee1394/dv\n"); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394); return -ENOMEM; } @@ -2838,7 +2945,7 @@ #ifdef CONFIG_PROC_FS if (dv1394_procfs_add_dir("dv",NULL,NULL) < 0) { - printk(KERN_ERR "dv1394: unable to create /proc/bus/%s\n", DV1394_DEV_BASE); + printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/dv\n"); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394); #ifdef CONFIG_DEVFS_FS dv1394_devfs_del("dv"); |
From: SVN U. <ben...@li...> - 2003-02-01 14:23:34
|
Author: bencollins Date: 2003-01-23 19:37:12 -0500 (Thu, 23 Jan 2003) New Revision: 757 Modified: trunk/ieee1394_core.c Log: Merge in newer module interfaces from 2.5.59. Modified: trunk/ieee1394_core.c ============================================================================== --- trunk/ieee1394_core.c (original) +++ trunk/ieee1394_core.c 2003-02-01 08:59:37.000000000 -0500 @@ -1055,7 +1055,7 @@ { int ret = 0; - if( (blocknum < 0) || (blocknum > 15) ) + if ((blocknum < 0) || (blocknum > 15)) return ret; read_lock(&ieee1394_chardevs_lock); @@ -1063,11 +1063,10 @@ *module = ieee1394_chardevs[blocknum].module; *file_ops = ieee1394_chardevs[blocknum].file_ops; - if(*file_ops == NULL) + if (*file_ops == NULL) goto out; - /* don't need try_inc_mod_count if the driver is non-modular */ - if(*module && (try_inc_mod_count(*module) == 0)) + if (!try_module_get(*module)) goto out; /* success! */ @@ -1127,36 +1126,26 @@ if(retval == 0) { /* If the open() succeeded, then ieee1394 will be left - with an extra module reference, so we discard it here. - - The task-specific driver still has the extra - reference given to it by ieee1394_get_chardev(). - This extra reference prevents the module from - unloading while the file is open, and will be - dropped by the VFS when the file is released. - */ - - if(THIS_MODULE) - __MOD_DEC_USE_COUNT((struct module*) THIS_MODULE); - - /* note that if ieee1394 is compiled into the kernel, - THIS_MODULE will be (void*) NULL, hence the if and - the cast are necessary */ + * with an extra module reference, so we discard it here. + * + * The task-specific driver still has the extra reference + * given to it by ieee1394_get_chardev(). This extra + * reference prevents the module from unloading while the + * file is open, and will be dropped by the VFS when the + * file is released. */ + module_put(THIS_MODULE); } else { - - /* if the open() failed, then we need to drop the - extra reference we gave to the task-specific - driver */ - - if(module) - __MOD_DEC_USE_COUNT(module); - /* point the file's f_ops back to ieee1394. The VFS will then decrement ieee1394's reference count immediately after this function returns. */ file->f_op = &ieee1394_chardev_ops; + + /* If the open() failed, then we need to drop the extra + * reference we gave to the task-specific driver. */ + + module_put(module); } return retval; |
From: SVN U. <ben...@li...> - 2003-02-01 14:23:34
|
Author: bencollins Date: 2003-01-23 18:52:07 -0500 (Thu, 23 Jan 2003) New Revision: 756 Added: tags/linux-2.4-sync/ Log: New 2.4 tag Copied: linux-2.4-sync (from rev 754, branches/linux-2.4) |
From: SVN U. <dm...@li...> - 2003-02-01 14:00:04
|
Author: dmaas Date: 2003-01-15 06:43:05 -0500 (Wed, 15 Jan 2003) New Revision: 750 Modified: trunk/hosts.h trunk/iso.c trunk/ohci1394.c Log: rawiso - more cleanups Modified: trunk/ohci1394.c ============================================================================== --- trunk/ohci1394.c (original) +++ trunk/ohci1394.c 2003-02-01 08:59:31.000000000 -0500 @@ -1490,16 +1490,13 @@ recv->block_reader = (recv->block_reader + 1) % recv->nblocks; } -static void ohci_iso_recv_release_one_packet(struct hpsb_iso *iso, struct ohci_iso_recv *recv) +static void ohci_iso_recv_release(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info) { - int flags; + struct ohci_iso_recv *recv = iso->hostdata; int len; /* release the memory where the packet was */ - /* note: we can't trust len, but the worst the user - can do is mess up his own received packets */ - - len = iso->infos[iso->first_packet].len; + len = info->len; /* add the wasted space for padding to 4 bytes */ if(len % 4) @@ -1515,20 +1512,6 @@ ohci_iso_recv_release_block(iso, recv); recv->released_bytes -= PAGE_SIZE; } - - /* advance packet cursors */ - iso->first_packet = (iso->first_packet+1) % iso->buf_packets; - - spin_lock_irqsave(&iso->lock, flags); - iso->n_ready_packets--; - spin_unlock_irqrestore(&iso->lock, flags); -} - -static void ohci_iso_recv_release(struct hpsb_iso *iso, int n_packets) -{ - int i; - for(i = 0; i < n_packets; i++) - ohci_iso_recv_release_one_packet(iso, (struct ohci_iso_recv*) iso->hostdata); } /* parse all packets from blocks that have been fully received */ @@ -2017,7 +2000,7 @@ ohci_iso_recv_stop(iso); return 0; case RECV_RELEASE: - ohci_iso_recv_release(iso, arg); + ohci_iso_recv_release(iso, (struct hpsb_iso_packet_info*) arg); return 0; case RECV_SHUTDOWN: ohci_iso_recv_shutdown(iso); Modified: trunk/hosts.h ============================================================================== --- trunk/hosts.h (original) +++ trunk/hosts.h 2003-02-01 08:59:32.000000000 -0500 @@ -108,9 +108,9 @@ enum isoctl_cmd { /* rawiso API - see iso.h for the meanings of these commands * INIT = allocate resources - * START = begin transmission/reception (arg: cycle to start on) + * START = begin transmission/reception * STOP = halt transmission/reception - * QUEUE/RELEASE = produce/consume packets (arg: # of packets) + * QUEUE/RELEASE = produce/consume packets * SHUTDOWN = deallocate resources */ Modified: trunk/iso.c ============================================================================== --- trunk/iso.c (original) +++ trunk/iso.c 2003-02-01 08:59:32.000000000 -0500 @@ -388,7 +388,6 @@ if(iso->n_ready_packets == iso->buf_packets) { /* overflow! */ atomic_inc(&iso->overflows); - return; } else { struct hpsb_iso_packet_info *info = &iso->infos[iso->pkt_dma]; info->offset = offset; @@ -407,10 +406,25 @@ int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets) { + unsigned long flags; + unsigned int i; + int rv = 0; + if(iso->type != HPSB_ISO_RECV) return -1; - return iso->host->driver->isoctl(iso, RECV_RELEASE, n_packets); + spin_lock_irqsave(&iso->lock, flags); + for(i = 0; i < n_packets; i++) { + rv = iso->host->driver->isoctl(iso, RECV_RELEASE, + (unsigned long) &iso->infos[iso->first_packet]); + if(rv) + break; + + iso->first_packet = (iso->first_packet+1) % iso->buf_packets; + iso->n_ready_packets--; + } + spin_unlock_irqrestore(&iso->lock, flags); + return rv; } void hpsb_iso_wake(struct hpsb_iso *iso) |
From: SVN U. <dm...@li...> - 2003-02-01 14:00:03
|
Author: dmaas Date: 2003-01-15 06:32:32 -0500 (Wed, 15 Jan 2003) New Revision: 749 Modified: trunk/ieee1394_core.c trunk/iso.c trunk/iso.h trunk/ohci1394.c trunk/raw1394.c trunk/raw1394.h Log: rawiso update - unify common code in iso.c and other housekeeping cleanups - no functionality changes Modified: trunk/iso.h ============================================================================== --- trunk/iso.h (original) +++ trunk/iso.h 2003-02-01 08:59:29.000000000 -0500 @@ -63,6 +63,9 @@ arrived */ void (*callback)(struct hpsb_iso*); + /* wait for buffer space */ + wait_queue_head_t waitq; + int speed; /* SPEED_100, 200, or 400 */ int channel; /* -1 if multichannel */ @@ -89,6 +92,10 @@ or consumed by the user */ int first_packet; + /* the index of the next packet that will be transmitted + or received by the 1394 hardware */ + int pkt_dma; + /* how many packets, starting at first_packet: (transmit) are ready to be filled with data (receive) contain received data */ @@ -146,8 +153,12 @@ /* deallocate buffer and DMA context */ void hpsb_iso_shutdown(struct hpsb_iso *iso); -/* N packets have been written to the buffer; queue them for transmission */ -int hpsb_iso_xmit_queue_packets(struct hpsb_iso *xmit, unsigned int n_packets); +/* queue a packet for transmission. 'offset' is relative to the beginning of the + DMA buffer, where the packet's data payload should already have been placed */ +int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag, u8 sy); + +/* wait until all queued packets have been transmitted to the bus */ +int hpsb_iso_xmit_sync(struct hpsb_iso *iso); /* N packets have been read out of the buffer, re-use the buffer space */ int hpsb_iso_recv_release_packets(struct hpsb_iso *recv, unsigned int n_packets); @@ -155,10 +166,19 @@ /* returns # of packets ready to send or receive */ int hpsb_iso_n_ready(struct hpsb_iso *iso); -/* check to make sure the user has not supplied bogus offset/len values that would - cause the kernel to access memory outside the buffer. Writes the sanitized values - to *offset and *len. Returns 0 if OK, otherwise -EFAULT or -EINVAL. */ -int hpsb_iso_check_offset_len(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info, - unsigned int *out_offset, unsigned short *out_len); +/* the following are callbacks available to low-level drivers */ + +/* call after a packet has been transmitted to the bus (interrupt context is OK) + 'cycle' is the _exact_ cycle the packet was sent on + 'error' should be non-zero if some sort of error occurred when sending the packet +*/ +void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error); + +/* call after a packet has been received (interrupt context OK) */ +void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len, + u16 cycle, u8 channel, u8 tag, u8 sy); + +/* call to wake waiting processes after buffer space has opened up. */ +void hpsb_iso_wake(struct hpsb_iso *iso); #endif /* IEEE1394_ISO_H */ Modified: trunk/ieee1394_core.c ============================================================================== --- trunk/ieee1394_core.c (original) +++ trunk/ieee1394_core.c 2003-02-01 08:59:29.000000000 -0500 @@ -1313,7 +1313,11 @@ EXPORT_SYMBOL(hpsb_iso_recv_set_channel_mask); EXPORT_SYMBOL(hpsb_iso_stop); EXPORT_SYMBOL(hpsb_iso_shutdown); -EXPORT_SYMBOL(hpsb_iso_xmit_queue_packets); +EXPORT_SYMBOL(hpsb_iso_xmit_queue_packet); +EXPORT_SYMBOL(hpsb_iso_xmit_sync); EXPORT_SYMBOL(hpsb_iso_recv_release_packets); EXPORT_SYMBOL(hpsb_iso_n_ready); -EXPORT_SYMBOL(hpsb_iso_check_offset_len); +EXPORT_SYMBOL(hpsb_iso_packet_sent); +EXPORT_SYMBOL(hpsb_iso_packet_received); +EXPORT_SYMBOL(hpsb_iso_wake); + Modified: trunk/ohci1394.c ============================================================================== --- trunk/ohci1394.c (original) +++ trunk/ohci1394.c 2003-02-01 08:59:29.000000000 -0500 @@ -1120,9 +1120,6 @@ /* the following four fields are used exclusively by the interrupt (no locking is required) */ - /* index into the info array for next packet to appear */ - int pkt_dma; - /* block that DMA will finish next */ int block_dma; @@ -1175,24 +1172,19 @@ recv->block = NULL; recv->nblocks = nblocks; -#if 0 - /* DJM - disable for now; irq_interval > 1 results in many overflows... */ /* iso->irq_interval is in packets - translate that to blocks */ - recv->block_irq_interval = (iso->irq_interval * iso->max_packet_size) / PAGE_SIZE; + /* (err, sort of... 1 is always the safest value) */ + recv->block_irq_interval = iso->irq_interval / nblocks; if(recv->block_irq_interval < 1) recv->block_irq_interval = 1; else if(recv->block_irq_interval*4 > recv->nblocks) recv->block_irq_interval = nblocks/4; -#else - recv->block_irq_interval = 1; -#endif recv->block_reader = 0; recv->released_bytes = 0; recv->block_dma = 0; recv->dma_offset = recv->block_dma * PAGE_SIZE; - recv->pkt_dma = 0; recv->warn_backoff = 0; /* size of DMA program = one INPUT_MORE per block */ @@ -1553,7 +1545,6 @@ unsigned short len, cycle; unsigned char channel, tag, sy; - unsigned long flags; unsigned char *p = iso->data_buf.kvirt; unsigned int this_block = recv->dma_offset/PAGE_SIZE; @@ -1638,52 +1629,11 @@ recv->dma_offset -= PAGE_SIZE*recv->nblocks; } - /* check if we have overflowed the ringbuffer of packet_infos */ - spin_lock_irqsave(&iso->lock, flags); - if(iso->n_ready_packets == iso->buf_packets) { - /* overflow! */ - atomic_inc(&iso->overflows); - - if(recv->warn_backoff == 0) { - DBGMSG(recv->ohci->id, - "ISO reception overflow - packet info buffer full"); - recv->warn_backoff = 10000; - } else { - recv->warn_backoff--; - } - - } else { - /* good, no overflow; fill out the packet_info */ - struct hpsb_iso_packet_info *info = &iso->infos[recv->pkt_dma]; - info->offset = offset; - info->len = len; - info->cycle = cycle; - info->channel = channel; - info->tag = tag; - info->sy = sy; - wmb(); - - /* one more packet for the user, one less for us */ - recv->pkt_dma = (recv->pkt_dma + 1) % iso->buf_packets; - iso->n_ready_packets++; - - if(iso->n_ready_packets*2 > iso->buf_packets) { - if(recv->warn_backoff == 0) { - DBGMSG(recv->ohci->id, - "Running out of packet info buffer space " - "for ISO reception - overrun likely (%u/%u packets)", - iso->n_ready_packets, iso->buf_packets); - recv->warn_backoff = 10000; - } else { - recv->warn_backoff--; - } - } - } - spin_unlock_irqrestore(&iso->lock, flags); + hpsb_iso_packet_received(iso, offset, len, cycle, channel, tag, sy); } - if(wake && iso->callback) - iso->callback(iso); + if(wake) + hpsb_iso_wake(iso); } static void ohci_iso_recv_task(unsigned long data) @@ -1757,7 +1707,6 @@ struct dma_prog_region prog; struct ohci1394_iso_tasklet task; int task_active; - int pkt_dma; u32 ContextControlSet; u32 ContextControlClear; @@ -1794,7 +1743,6 @@ iso->hostdata = xmit; xmit->ohci = iso->host->hostdata; xmit->task_active = 0; - xmit->pkt_dma = iso->first_packet; dma_prog_region_init(&xmit->prog); @@ -1859,17 +1807,15 @@ { struct hpsb_iso *iso = (struct hpsb_iso*) data; struct ohci_iso_xmit *xmit = iso->hostdata; - unsigned long flags; int wake = 0; int count; - spin_lock_irqsave(&iso->lock, flags); - /* check the whole buffer if necessary, starting at pkt_dma */ for(count = 0; count < iso->buf_packets; count++) { - + int cycle; + /* DMA descriptor */ - struct iso_xmit_cmd *cmd = dma_region_i(&xmit->prog, struct iso_xmit_cmd, xmit->pkt_dma); + struct iso_xmit_cmd *cmd = dma_region_i(&xmit->prog, struct iso_xmit_cmd, iso->pkt_dma); /* check for new writes to xferStatus */ u16 xferstatus = cmd->output_last.status >> 16; @@ -1880,51 +1826,29 @@ break; } - if(event != 0x11) { - atomic_inc(&iso->overflows); - PRINT(KERN_ERR, xmit->ohci->id, "IT DMA error - OHCI error code 0x%02x\n", event); - } + if(event != 0x11) + PRINT(KERN_ERR, xmit->ohci->id, + "IT DMA error - OHCI error code 0x%02x\n", event); /* at least one packet went out, so wake up the writer */ wake = 1; /* parse cycle */ - { - unsigned int cycle = cmd->output_last.status & 0x1FFF; - - /* predict the timestamp of the next packet to be queued */ - - /* jump ahead by the number of packets that are already buffered */ - cycle += iso->buf_packets - iso->n_ready_packets; - while(cycle >= 8000) - cycle -= 8000; - - iso->xmit_cycle = cycle; - } + cycle = cmd->output_last.status & 0x1FFF; + /* tell the subsystem the packet has gone out */ + hpsb_iso_packet_sent(iso, cycle, event != 0x11); + /* reset the DMA descriptor for next time */ cmd->output_last.status = 0; - - /* advance packet cursor */ - xmit->pkt_dma = (xmit->pkt_dma + 1) % iso->buf_packets; - iso->n_ready_packets += 1; - - if(iso->n_ready_packets == iso->buf_packets) { - /* underflow */ - atomic_inc(&iso->overflows); - } } - spin_unlock_irqrestore(&iso->lock, flags); - - if(wake && iso->callback) { - iso->callback(iso); - } + if(wake) + hpsb_iso_wake(iso); } -static int ohci_iso_xmit_queue_one(struct hpsb_iso *iso) +static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info) { - unsigned long flags; struct ohci_iso_xmit *xmit = iso->hostdata; int next_i, prev_i; @@ -1934,30 +1858,20 @@ unsigned short len; unsigned char tag, sy; - /* grab the packet offset, length, tag, and sy fields from the - buffer. NOTE: we cannot trust the user to supply a valid - offset and length! */ - { - struct hpsb_iso_packet_info *info = &iso->infos[iso->first_packet]; - - /* check for bogus offset/length */ - int ret = hpsb_iso_check_offset_len(iso, info, &offset, &len); - if(ret) - return ret; - - /* also check that the packet doesn't cross a page boundary - (we could allow this if we added OUTPUT_MORE descriptor support) */ - if(cross_bound(offset, len)) { - PRINT(KERN_ERR, xmit->ohci->id, - "rawiso xmit: packet %u crosses a page boundary", - iso->first_packet); - return -EINVAL; - } - - tag = info->tag; - sy = info->sy; + /* check that the packet doesn't cross a page boundary + (we could allow this if we added OUTPUT_MORE descriptor support) */ + if(cross_bound(info->offset, info->len)) { + PRINT(KERN_ERR, xmit->ohci->id, + "rawiso xmit: packet %u crosses a page boundary", + iso->first_packet); + return -EINVAL; } + offset = info->offset; + len = info->len; + tag = info->tag; + sy = info->sy; + /* sync up the card's view of the buffer */ dma_region_sync(&iso->data_buf, offset, len); @@ -2025,24 +1939,6 @@ mb(); reg_read(xmit->ohci, OHCI1394_IsochronousCycleTimer); - /* increment cursors */ - spin_lock_irqsave(&iso->lock, flags); - iso->first_packet = (iso->first_packet+1) % iso->buf_packets; - iso->xmit_cycle = (iso->xmit_cycle+1) % 8000; - iso->n_ready_packets--; - spin_unlock_irqrestore(&iso->lock, flags); - - return 0; -} - -static int ohci_iso_xmit_queue(struct hpsb_iso *iso, int n_packets) -{ - int i, ret; - for(i = 0; i < n_packets; i++) { - ret = ohci_iso_xmit_queue_one(iso); - if(ret) - return ret; - } return 0; } @@ -2056,7 +1952,7 @@ /* address and length of first descriptor block (Z=3) */ reg_write(xmit->ohci, xmit->CommandPtr, - dma_prog_region_offset_to_bus(&xmit->prog, xmit->pkt_dma * sizeof(struct iso_xmit_cmd)) | 3); + dma_prog_region_offset_to_bus(&xmit->prog, iso->pkt_dma * sizeof(struct iso_xmit_cmd)) | 3); /* cycle match */ if(cycle != -1) { @@ -2101,12 +1997,12 @@ case XMIT_INIT: return ohci_iso_xmit_init(iso); case XMIT_START: - return ohci_iso_xmit_start(iso, arg < 8000 ? arg : -1); + return ohci_iso_xmit_start(iso, arg); case XMIT_STOP: ohci_iso_xmit_stop(iso); return 0; case XMIT_QUEUE: - return ohci_iso_xmit_queue(iso, arg); + return ohci_iso_xmit_queue(iso, (struct hpsb_iso_packet_info*) arg); case XMIT_SHUTDOWN: ohci_iso_xmit_shutdown(iso); return 0; Modified: trunk/raw1394.c ============================================================================== --- trunk/raw1394.c (original) +++ trunk/raw1394.c 2003-02-01 08:59:30.000000000 -0500 @@ -2180,8 +2180,7 @@ static int raw1394_iso_send_packets(struct file_info *fi, void *uaddr) { struct raw1394_iso_packets upackets; - unsigned int packet = fi->iso_handle->first_packet; - int i; + int i, rv; if(copy_from_user(&upackets, uaddr, sizeof(upackets))) return -EFAULT; @@ -2194,17 +2193,21 @@ upackets.n_packets * sizeof(struct raw1394_iso_packet_info))) return -EFAULT; - /* copy the packet_infos in */ + /* copy the infos structs in and queue the packets */ for(i = 0; i < upackets.n_packets; i++) { - if(__copy_from_user(&fi->iso_handle->infos[packet], - &upackets.infos[i], + struct raw1394_iso_packet_info info; + + if(__copy_from_user(&info, &upackets.infos[i], sizeof(struct raw1394_iso_packet_info))) return -EFAULT; - - packet = (packet + 1) % fi->iso_handle->buf_packets; + + rv = hpsb_iso_xmit_queue_packet(fi->iso_handle, info.offset, + info.len, info.tag, info.sy); + if(rv) + return rv; } - return hpsb_iso_xmit_queue_packets(fi->iso_handle, upackets.n_packets); + return 0; } static void raw1394_iso_shutdown(struct file_info *fi) @@ -2289,6 +2292,8 @@ return -EFAULT; return hpsb_iso_xmit_start(fi->iso_handle, args[0], args[1]); } + case RAW1394_ISO_XMIT_SYNC: + return hpsb_iso_xmit_sync(fi->iso_handle); case RAW1394_ISO_STOP: hpsb_iso_stop(fi->iso_handle); return 0; Modified: trunk/raw1394.h ============================================================================== --- trunk/raw1394.h (original) +++ trunk/raw1394.h 2003-02-01 08:59:30.000000000 -0500 @@ -133,7 +133,8 @@ #define RAW1394_ISO_RECV_PACKETS 13 /* arg: struct raw1394_iso_packets* */ #define RAW1394_ISO_RECV_RELEASE_PACKETS 14 /* arg: int n_packets */ #define RAW1394_ISO_XMIT_PACKETS 15 /* arg: struct raw1394_iso_packets* */ - +#define RAW1394_ISO_XMIT_SYNC 16 + /* per-packet metadata embedded in the ringbuffer */ /* must be identical to hpsb_iso_packet_info in iso.h! */ struct raw1394_iso_packet_info { Modified: trunk/iso.c ============================================================================== --- trunk/iso.c (original) +++ trunk/iso.c 2003-02-01 08:59:30.000000000 -0500 @@ -80,11 +80,13 @@ iso->host = host; iso->hostdata = NULL; iso->callback = callback; + init_waitqueue_head(&iso->waitq); iso->channel = channel; iso->irq_interval = irq_interval; dma_region_init(&iso->data_buf); iso->buf_size = round_up_to_page(data_buf_size); iso->buf_packets = buf_packets; + iso->pkt_dma = 0; iso->first_packet = 0; spin_lock_init(&iso->lock); @@ -223,7 +225,9 @@ iso->xmit_cycle = cycle; - if(prebuffer < 1) + if(prebuffer < 0) + prebuffer = iso->buf_packets; + else if(prebuffer == 0) prebuffer = 1; if(prebuffer > iso->buf_packets) @@ -271,60 +275,148 @@ return retval; } -int hpsb_iso_xmit_queue_packets(struct hpsb_iso *iso, unsigned int n_packets) +/* check to make sure the user has not supplied bogus values of offset/len + that would cause the kernel to access memory outside the buffer */ + +static int hpsb_iso_check_offset_len(struct hpsb_iso *iso, + unsigned int offset, unsigned short len, + unsigned int *out_offset, unsigned short *out_len) { - int retval; + if(offset >= iso->buf_size) + return -EFAULT; + + /* make sure the packet does not go beyond the end of the buffer */ + if(offset + len > iso->buf_size) + return -EFAULT; + + /* check for wrap-around */ + if(offset + len < offset) + return -EFAULT; + + /* now we can trust 'offset' and 'length' */ + *out_offset = offset; + *out_len = len; + + return 0; +} + + +int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag, u8 sy) +{ + struct hpsb_iso_packet_info *info; + unsigned long flags; + int rv; if(iso->type != HPSB_ISO_XMIT) - return -1; + return -EINVAL; - retval = iso->host->driver->isoctl(iso, XMIT_QUEUE, n_packets); - if(retval) - return retval; + /* is there space in the buffer? */ + if(iso->n_ready_packets <= 0) { + return -EBUSY; + } + + info = &iso->infos[iso->first_packet]; + + /* check for bogus offset/length */ + if(hpsb_iso_check_offset_len(iso, offset, len, &info->offset, &info->len)) + return -EFAULT; + + info->tag = tag; + info->sy = sy; + + spin_lock_irqsave(&iso->lock, flags); + + rv = iso->host->driver->isoctl(iso, XMIT_QUEUE, (unsigned long) info); + if(rv) + goto out; + + /* increment cursors */ + iso->first_packet = (iso->first_packet+1) % iso->buf_packets; + iso->xmit_cycle = (iso->xmit_cycle+1) % 8000; + iso->n_ready_packets--; if(iso->prebuffer != 0) { - iso->prebuffer -= n_packets; + iso->prebuffer--; if(iso->prebuffer <= 0) { iso->prebuffer = 0; - return do_iso_xmit_start(iso, - iso->start_cycle); + rv = do_iso_xmit_start(iso, iso->start_cycle); } } - return 0; +out: + spin_unlock_irqrestore(&iso->lock, flags); + return rv; } -int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets) +int hpsb_iso_xmit_sync(struct hpsb_iso *iso) { - if(iso->type != HPSB_ISO_RECV) - return -1; + if(iso->type != HPSB_ISO_XMIT) + return -EINVAL; - return iso->host->driver->isoctl(iso, RECV_RELEASE, n_packets); + return wait_event_interruptible(iso->waitq, hpsb_iso_n_ready(iso) == iso->buf_packets); } -int hpsb_iso_check_offset_len(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info, - unsigned int *out_offset, unsigned short *out_len) +void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error) { - unsigned int offset, len; + unsigned long flags; + spin_lock_irqsave(&iso->lock, flags); - offset = info->offset; + /* predict the cycle of the next packet to be queued */ - if(offset >= iso->buf_size) - return -EFAULT; + /* jump ahead by the number of packets that are already buffered */ + cycle += iso->buf_packets - iso->n_ready_packets; + cycle %= 8000; - len = info->len; + iso->xmit_cycle = cycle; + iso->n_ready_packets++; + iso->pkt_dma = (iso->pkt_dma + 1) % iso->buf_packets; - /* make sure the packet does not go beyond the end of the buffer */ - if(offset + len > iso->buf_size) - return -EFAULT; + if(iso->n_ready_packets == iso->buf_packets || error != 0) { + /* the buffer has run empty! */ + atomic_inc(&iso->overflows); + } - /* check for wrap-around */ - if(offset + len < offset) - return -EFAULT; + spin_unlock_irqrestore(&iso->lock, flags); +} - /* now we can trust 'offset' and 'length' */ - *out_offset = offset; - *out_len = len; +void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len, + u16 cycle, u8 channel, u8 tag, u8 sy) +{ + unsigned long flags; + spin_lock_irqsave(&iso->lock, flags); - return 0; + if(iso->n_ready_packets == iso->buf_packets) { + /* overflow! */ + atomic_inc(&iso->overflows); + return; + } else { + struct hpsb_iso_packet_info *info = &iso->infos[iso->pkt_dma]; + info->offset = offset; + info->len = len; + info->cycle = cycle; + info->channel = channel; + info->tag = tag; + info->sy = sy; + + iso->pkt_dma = (iso->pkt_dma+1) % iso->buf_packets; + iso->n_ready_packets++; + } + + spin_unlock_irqrestore(&iso->lock, flags); +} + +int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets) +{ + if(iso->type != HPSB_ISO_RECV) + return -1; + + return iso->host->driver->isoctl(iso, RECV_RELEASE, n_packets); +} + +void hpsb_iso_wake(struct hpsb_iso *iso) +{ + wake_up_interruptible(&iso->waitq); + + if(iso->callback) + iso->callback(iso); } |
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); |
From: SVN U. <dm...@li...> - 2003-02-01 13:59:59
|
Author: dmaas Date: 2003-01-15 03:38:34 -0500 (Wed, 15 Jan 2003) New Revision: 747 Modified: trunk/highlevel.c Log: fix typo in previous commit Modified: trunk/highlevel.c ============================================================================== --- trunk/highlevel.c (original) +++ trunk/highlevel.c 2003-02-01 08:59:26.000000000 -0500 @@ -175,6 +175,8 @@ if (host->iso_listen_count[channel]++ == 0) { return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel); } + + return 0; } void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, |
From: SVN U. <dm...@li...> - 2003-02-01 13:59:58
|
Author: dmaas Date: 2003-01-15 03:36:16 -0500 (Wed, 15 Jan 2003) New Revision: 746 Modified: trunk/highlevel.c trunk/highlevel.h trunk/ohci1394.c trunk/ohci1394.h trunk/raw1394.c Log: ohci1394 - allocate legacy API IR context on-demand (this allows new rawiso programs to use multi-channel reception) changed hpsb_listen_channel so that it can return an error if the multichannel context cannot be allocated Modified: trunk/ohci1394.c ============================================================================== --- trunk/ohci1394.c (original) +++ trunk/ohci1394.c 2003-02-01 08:59:25.000000000 -0500 @@ -170,6 +170,11 @@ static void dma_trm_tasklet(unsigned long data); static void dma_trm_reset(struct dma_trm_ctx *d); +static int alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d, + enum context_type type, int ctx, int num_desc, + int buf_size, int split_buf_size, int context_base); +static void free_dma_rcv_ctx(struct dma_rcv_ctx *d); + static void ohci1394_pci_remove(struct pci_dev *pdev); #ifndef __LITTLE_ENDIAN @@ -415,10 +420,28 @@ d->buf_ind = 0; d->buf_offset = 0; + if(d->type == DMA_CTX_ISO) { + /* Clear contextControl */ + reg_write(ohci, d->ctrlClear, 0xffffffff); + + /* Set bufferFill, isochHeader, multichannel for IR context */ + reg_write(ohci, d->ctrlSet, 0xd0000000); + + /* Set the context match register to match on all tags */ + reg_write(ohci, d->ctxtMatch, 0xf0000000); + + /* Clear the multi channel mask high and low registers */ + reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 0xffffffff); + reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff); + + /* Set up isoRecvIntMask to generate interrupts */ + reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << d->ctx); + } + /* Tell the controller where the first AR program is */ reg_write(ohci, d->cmdPtr, d->prg_bus[0] | 0x1); - /* Run AR context */ + /* Run context */ reg_write(ohci, d->ctrlSet, 0x00008000); DBGMSG(ohci->id, "Receive DMA ctx=%d initialized", d->ctx); @@ -515,12 +538,6 @@ /* Don't accept phy packets into AR request context */ reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400); - /* Set bufferFill, isochHeader, multichannel for IR context */ - reg_write(ohci, OHCI1394_IsoRcvContextControlSet, 0xd0000000); - - /* Set the context match register to match on all tags */ - reg_write(ohci, OHCI1394_IsoRcvContextMatch, 0xf0000000); - /* Clear the interrupt mask */ reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff); reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff); @@ -529,10 +546,6 @@ reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff); reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff); - /* Clear the multi channel mask high and low registers */ - reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 0xffffffff); - reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff); - /* Initialize AR dma */ initialize_dma_rcv_ctx(&ohci->ar_req_context, 0); initialize_dma_rcv_ctx(&ohci->ar_resp_context, 0); @@ -541,16 +554,9 @@ initialize_dma_trm_ctx(&ohci->at_req_context); initialize_dma_trm_ctx(&ohci->at_resp_context); - /* Initialize IR dma */ - initialize_dma_rcv_ctx(&ohci->ir_context, 1); - /* Initialize IT dma */ initialize_dma_trm_ctx(&ohci->it_context); - /* Set up isoRecvIntMask to generate interrupts for context 0 - (thanks to Michael Greger for seeing that I forgot this) */ - reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 0x00000001); - /* Set up isoXmitIntMask to generate interrupts for context 0 */ reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 0x00000001); @@ -962,8 +968,27 @@ spin_unlock_irqrestore(&ohci->IR_channel_lock, flags); return -EFAULT; } - + + /* activate the legacy IR context */ + if(!ohci->ir_legacy_active) { + if(alloc_dma_rcv_ctx(ohci, &ohci->ir_legacy_context, + DMA_CTX_ISO, 0, IR_NUM_DESC, + IR_BUF_SIZE, IR_SPLIT_BUF_SIZE, + OHCI1394_IsoRcvContextBase) < 0) { + PRINT(KERN_ERR, ohci->id, + "%s: failed to allocate an IR context", + __FUNCTION__); + return -ENOMEM; + } + ohci->ir_legacy_active = 1; + ohci->ir_legacy_channels = 0; + initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1); + + DBGMSG(ohci->id, "ISO receive legacy context activated"); + } + ohci->ISO_channel_usage |= mask; + ohci->ir_legacy_channels |= mask; if (arg>31) reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet, @@ -1000,6 +1025,7 @@ } ohci->ISO_channel_usage &= ~mask; + ohci->ir_legacy_channels &= ~mask; if (arg>31) reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, @@ -1010,6 +1036,12 @@ 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) { + free_dma_rcv_ctx(&ohci->ir_legacy_context); + DBGMSG(ohci->id, "ISO receive legacy context deactivated"); + ohci->ir_legacy_active = 0; + } break; } default: @@ -2205,7 +2237,7 @@ for (ctx = 0; ctx < ohci->nb_iso_xmit_ctx; ctx++) { if (reg_read(ohci, OHCI1394_IsoXmitContextControlSet + (16 * ctx)) & 0x800) - PRINT(KERN_ERR, ohci->id, "Async Iso Xmit %d Context died: " + PRINT(KERN_ERR, ohci->id, "Iso Xmit %d Context died: " "ctrl[%08x] cmdptr[%08x]", ctx, reg_read(ohci, OHCI1394_IsoXmitContextControlSet + (16 * ctx)), reg_read(ohci, OHCI1394_IsoXmitCommandPtr + (16 * ctx))); @@ -2213,7 +2245,7 @@ for (ctx = 0; ctx < ohci->nb_iso_rcv_ctx; ctx++) { if (reg_read(ohci, OHCI1394_IsoRcvContextControlSet + (32 * ctx)) & 0x800) - PRINT(KERN_ERR, ohci->id, "Async Iso Recv %d Context died: " + PRINT(KERN_ERR, ohci->id, "Iso Recv %d Context died: " "ctrl[%08x] cmdptr[%08x] match[%08x]", ctx, reg_read(ohci, OHCI1394_IsoRcvContextControlSet + (32 * ctx)), reg_read(ohci, OHCI1394_IsoRcvCommandPtr + (32 * ctx)), @@ -2401,8 +2433,10 @@ PRINT(KERN_INFO, ohci->id, "Waking dma ctx=%d ... processing is probably too slow", d->ctx); - reg_write(ohci, d->ctrlSet, 0x1000); } + + /* do this always, to avoid race condition */ + reg_write(ohci, d->ctrlSet, 0x1000); } #define cond_le32_to_cpu(data, noswap) \ @@ -2716,12 +2750,17 @@ DBGMSG(d->ohci->id, "Freeing dma_rcv_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->ir_tasklet); - else - tasklet_kill(&d->task); + if (d->type == DMA_CTX_ISO) { + /* disable interrupts */ + reg_write(d->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << d->ctx); + ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->ir_legacy_tasklet); + } else { + tasklet_kill(&d->task); + } + } if (d->buf_cpu) { for (i=0; i<d->num_desc; i++) @@ -2766,9 +2805,9 @@ d->buf_size = buf_size; d->split_buf_size = split_buf_size; - 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->buf_cpu = kmalloc(d->num_desc * sizeof(quadlet_t*), GFP_KERNEL); d->buf_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL); @@ -2836,17 +2875,30 @@ spin_lock_init(&d->lock); if (type == DMA_CTX_ISO) { - ohci1394_init_iso_tasklet(&ohci->ir_tasklet, OHCI_ISO_MULTICHANNEL_RECEIVE, + ohci1394_init_iso_tasklet(&ohci->ir_legacy_tasklet, + OHCI_ISO_MULTICHANNEL_RECEIVE, dma_rcv_tasklet, (unsigned long) d); if (ohci1394_register_iso_tasklet(ohci, - &ohci->ir_tasklet) < 0) { + &ohci->ir_legacy_tasklet) < 0) { PRINT(KERN_ERR, ohci->id, "No IR DMA context available"); free_dma_rcv_ctx(d); return -EBUSY; } - } - else + + /* the IR context can be assigned to any DMA context + * by ohci1394_register_iso_tasklet */ + d->ctx = ohci->ir_legacy_tasklet.context; + d->ctrlSet = OHCI1394_IsoRcvContextControlSet + 32*d->ctx; + d->ctrlClear = OHCI1394_IsoRcvContextControlClear + 32*d->ctx; + d->cmdPtr = OHCI1394_IsoRcvCommandPtr + 32*d->ctx; + d->ctxtMatch = OHCI1394_IsoRcvContextMatch + 32*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_rcv_tasklet, (unsigned long) d); + } return 0; } @@ -3296,13 +3348,8 @@ ohci->ISO_channel_usage = 0; spin_lock_init(&ohci->IR_channel_lock); - /* IR DMA context */ - if (alloc_dma_rcv_ctx(ohci, &ohci->ir_context, - DMA_CTX_ISO, 0, IR_NUM_DESC, - IR_BUF_SIZE, IR_SPLIT_BUF_SIZE, - OHCI1394_IsoRcvContextBase) < 0) - FAIL(-ENOMEM, "Failed to allocate IR context"); - + /* the IR DMA context is allocated on-demand */ + ohci->ir_legacy_active = 0; /* IT DMA context allocation */ if (alloc_dma_trm_ctx(ohci, &ohci->it_context, @@ -3353,7 +3400,8 @@ free_dma_trm_ctx(&ohci->at_resp_context); /* Free IR dma */ - free_dma_rcv_ctx(&ohci->ir_context); + if(ohci->ir_legacy_active) + free_dma_rcv_ctx(&ohci->ir_legacy_context); /* Free IT dma */ free_dma_trm_ctx(&ohci->it_context); Modified: trunk/ohci1394.h ============================================================================== --- trunk/ohci1394.h (original) +++ trunk/ohci1394.h 2003-02-01 08:59:25.000000000 -0500 @@ -109,6 +109,7 @@ int ctrlClear; int ctrlSet; int cmdPtr; + int ctxtMatch; }; /* DMA transmit context */ @@ -188,13 +189,21 @@ struct dma_trm_ctx at_req_context; /* iso receive */ - struct dma_rcv_ctx ir_context; - struct ohci1394_iso_tasklet ir_tasklet; - spinlock_t IR_channel_lock; int nb_iso_rcv_ctx; unsigned long ir_ctx_usage; /* use test_and_set_bit() for atomicity */ unsigned int ir_multichannel_used; /* ditto */ + 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 + it is safe to free the legacy API context */ + + struct dma_rcv_ctx ir_legacy_context; + struct ohci1394_iso_tasklet ir_legacy_tasklet; + /* iso transmit */ struct dma_trm_ctx it_context; struct ohci1394_iso_tasklet it_tasklet; Modified: trunk/raw1394.c ============================================================================== --- trunk/raw1394.c (original) +++ trunk/raw1394.c 2003-02-01 08:59:26.000000000 -0500 @@ -603,10 +603,13 @@ if (fi->listen_channels & (1ULL << channel)) { req->req.error = RAW1394_ERROR_ALREADY; } else { - fi->listen_channels |= 1ULL << channel; - hpsb_listen_channel(hl_handle, fi->host, channel); - fi->iso_buffer = int2ptr(req->req.recvb); - fi->iso_buffer_length = req->req.length; + if(hpsb_listen_channel(hl_handle, fi->host, channel)) { + req->req.error = RAW1394_ERROR_ALREADY; + } else { + fi->listen_channels |= 1ULL << channel; + fi->iso_buffer = int2ptr(req->req.recvb); + fi->iso_buffer_length = req->req.length; + } } } else { /* deallocate channel (one's complement neg) req.misc */ Modified: trunk/highlevel.c ============================================================================== --- trunk/highlevel.c (original) +++ trunk/highlevel.c 2003-02-01 08:59:26.000000000 -0500 @@ -164,16 +164,16 @@ return retval; } -void hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, +int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, unsigned int channel) { if (channel > 63) { HPSB_ERR("%s called with invalid channel", __FUNCTION__); - return; + return -EINVAL; } if (host->iso_listen_count[channel]++ == 0) { - host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel); + return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel); } } Modified: trunk/highlevel.h ============================================================================== --- trunk/highlevel.h (original) +++ trunk/highlevel.h 2003-02-01 08:59:26.000000000 -0500 @@ -150,8 +150,8 @@ * Enable or disable receving a certain isochronous channel through the * iso_receive op. */ -void hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, - unsigned int channel); +int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, + unsigned int channel); void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, unsigned int channel); |
From: SVN U. <dm...@li...> - 2003-02-01 13:59:56
|
Author: dmaas Date: 2003-01-15 01:34:29 -0500 (Wed, 15 Jan 2003) New Revision: 745 Modified: trunk/iso.c trunk/iso.h trunk/ohci1394.c trunk/raw1394.c trunk/raw1394.h Log: rawiso - implement tag matching; disable cycle continuity checking Modified: trunk/iso.h ============================================================================== --- trunk/iso.h (original) +++ trunk/iso.h 2003-02-01 08:59:22.000000000 -0500 @@ -140,7 +140,7 @@ /* start/stop DMA */ int hpsb_iso_xmit_start(struct hpsb_iso *iso, int start_on_cycle, int prebuffer); -int hpsb_iso_recv_start(struct hpsb_iso *iso, int start_on_cycle); +int hpsb_iso_recv_start(struct hpsb_iso *iso, int start_on_cycle, int tag_mask, int sync); void hpsb_iso_stop(struct hpsb_iso *iso); /* deallocate buffer and DMA context */ Modified: trunk/ohci1394.c ============================================================================== --- trunk/ohci1394.c (original) +++ trunk/ohci1394.c 2003-02-01 08:59:23.000000000 -0500 @@ -1058,9 +1058,6 @@ /* bytes of buffer the reader has released, less than one block */ int released_bytes; - /* cycle of last-received packet; used to detecting dropouts */ - int last_cycle; - /* the following four fields are used exclusively by the interrupt (no locking is required) */ @@ -1089,7 +1086,7 @@ static void ohci_iso_recv_stop(struct hpsb_iso *iso); static void ohci_iso_recv_shutdown(struct hpsb_iso *iso); static void ohci_iso_recv_program(struct hpsb_iso *iso); -static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle); +static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask); static int ohci_iso_recv_init(struct hpsb_iso *iso) @@ -1133,7 +1130,6 @@ recv->block_reader = 0; recv->released_bytes = 0; - recv->last_cycle = -1; recv->block_dma = 0; recv->dma_offset = recv->block_dma * PAGE_SIZE; @@ -1311,21 +1307,19 @@ reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer); } -static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle) +static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask) { struct ohci_iso_recv *recv = iso->hostdata; u32 command, contextMatch; - recv->last_cycle = -1; - reg_write(recv->ohci, recv->ContextControlClear, 0xFFFFFFFF); wmb(); /* use buffer-fill mode, and keep ISO headers (required for multichannel) */ reg_write(recv->ohci, recv->ContextControlSet, (1 << 31) | (1 << 30)); - /* match on all tags */ - contextMatch = 0xF0000000; + /* match on specified tags */ + contextMatch = tag_mask << 28; if(iso->channel == -1) { /* enable multichannel reception */ @@ -1577,19 +1571,6 @@ cycle = p[recv->dma_offset+0] | (p[recv->dma_offset+1]<<8); cycle &= 0x1FFF; - /* check for cycle discontinuity */ - if(recv->last_cycle != -1) { - /* for multichannel, we have to allow cycle == last_cycle */ - if((cycle != (recv->last_cycle+1) % 8000) && - (cycle != recv->last_cycle)) { - atomic_inc(&iso->overflows); - DBGMSG(recv->ohci->id, "ISO reception overflow - " - "cycle discontinuity detected (cycle %4u last %4d)", - cycle, recv->last_cycle); - } - } - recv->last_cycle = cycle; - /* advance to next packet */ recv->dma_offset += 4; @@ -1718,7 +1699,6 @@ struct ohci1394_iso_tasklet task; int task_active; int pkt_dma; - int last_cycle; u32 ContextControlSet; u32 ContextControlClear; @@ -1756,7 +1736,6 @@ xmit->ohci = iso->host->hostdata; xmit->task_active = 0; xmit->pkt_dma = iso->first_packet; - xmit->last_cycle = -1; dma_prog_region_init(&xmit->prog); @@ -1854,12 +1833,6 @@ { unsigned int cycle = cmd->output_last.status & 0x1FFF; - /* check for discontinuity */ - if(xmit->last_cycle != -1 && cycle != (xmit->last_cycle+1) % 8000) { - atomic_inc(&iso->overflows); - } - xmit->last_cycle = cycle; - /* predict the timestamp of the next packet to be queued */ /* jump ahead by the number of packets that are already buffered */ @@ -2018,8 +1991,6 @@ { struct ohci_iso_xmit *xmit = iso->hostdata; - xmit->last_cycle = -1; - /* clear out the control register */ reg_write(xmit->ohci, xmit->ContextControlClear, 0xFFFFFFFF); wmb(); @@ -2042,11 +2013,6 @@ start |= (seconds & 3) << 13; reg_write(xmit->ohci, xmit->ContextControlSet, 0x80000000 | (start << 16)); - - if(cycle == 0) - xmit->last_cycle = 7999; - else - xmit->last_cycle = cycle - 1; } /* enable interrupts */ @@ -2088,8 +2054,10 @@ case RECV_INIT: return ohci_iso_recv_init(iso); - case RECV_START: - return ohci_iso_recv_start(iso, arg < 8000 ? arg : -1); + case RECV_START: { + int *args = (int*) arg; + return ohci_iso_recv_start(iso, args[0], args[1]); + } case RECV_STOP: ohci_iso_recv_stop(iso); return 0; Modified: trunk/raw1394.c ============================================================================== --- trunk/raw1394.c (original) +++ trunk/raw1394.c 2003-02-01 08:59:24.000000000 -0500 @@ -2242,8 +2242,13 @@ break; case RAW1394_ISO_RECV: switch(cmd) { - case RAW1394_ISO_RECV_START: - return hpsb_iso_recv_start(fi->iso_handle, arg); + case RAW1394_ISO_RECV_START: { + /* copy args from user-space */ + int args[3]; + if(copy_from_user(&args[0], (void*) arg, sizeof(args))) + return -EFAULT; + return hpsb_iso_recv_start(fi->iso_handle, args[0], args[1], args[2]); + } case RAW1394_ISO_STOP: hpsb_iso_stop(fi->iso_handle); return 0; Modified: trunk/raw1394.h ============================================================================== --- trunk/raw1394.h (original) +++ trunk/raw1394.h 2003-02-01 08:59:24.000000000 -0500 @@ -120,7 +120,7 @@ /* ioctls */ #define RAW1394_ISO_XMIT_INIT 1 /* arg: raw1394_iso_status* */ #define RAW1394_ISO_RECV_INIT 2 /* arg: raw1394_iso_status* */ -#define RAW1394_ISO_RECV_START 3 /* arg: int, starting cycle */ +#define RAW1394_ISO_RECV_START 3 /* arg: int[3], { starting cycle, tag, sync } */ #define RAW1394_ISO_XMIT_START 8 /* arg: int[2], { starting cycle, prebuffer } */ #define RAW1394_ISO_STOP 4 #define RAW1394_ISO_GET_STATUS 5 /* arg: raw1394_iso_status* */ Modified: trunk/iso.c ============================================================================== --- trunk/iso.c (original) +++ trunk/iso.c 2003-02-01 08:59:24.000000000 -0500 @@ -238,9 +238,10 @@ return 0; } -int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle) +int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync) { int retval = 0; + int isoctl_args[3]; if(iso->type != HPSB_ISO_RECV) return -1; @@ -248,7 +249,21 @@ if(iso->flags & HPSB_ISO_DRIVER_STARTED) return 0; - retval = iso->host->driver->isoctl(iso, RECV_START, cycle); + if(cycle < -1) + cycle = -1; + else if(cycle >= 8000) + cycle %= 8000; + + isoctl_args[0] = cycle; + + if(tag_mask < 0) + /* match all tags */ + tag_mask = 0xF; + isoctl_args[1] = tag_mask; + + isoctl_args[2] = sync; + + retval = iso->host->driver->isoctl(iso, RECV_START, (unsigned long) &isoctl_args[0]); if(retval) return retval; |
From: SVN U. <dde...@li...> - 2003-02-01 13:59:54
|
Author: ddennedy Date: 2003-01-11 15:24:38 -0500 (Sat, 11 Jan 2003) New Revision: 744 Modified: branches/linux-2.4/ieee1394_core.c Log: export dma symbols 2 Modified: branches/linux-2.4/ieee1394_core.c ============================================================================== --- branches/linux-2.4/ieee1394_core.c (original) +++ branches/linux-2.4/ieee1394_core.c 2003-02-01 08:59:21.000000000 -0500 @@ -42,6 +42,7 @@ #include "csr.h" #include "nodemgr.h" #include "ieee1394_hotplug.h" +#include "dma.h" /* * Disable the nodemgr detection and config rom reading functionality. |
From: SVN U. <dde...@li...> - 2003-02-01 13:59:53
|
Author: ddennedy Date: 2003-01-11 15:11:02 -0500 (Sat, 11 Jan 2003) New Revision: 743 Modified: branches/linux-2.4/ieee1394_core.c Log: export dma symbols Modified: branches/linux-2.4/ieee1394_core.c ============================================================================== --- branches/linux-2.4/ieee1394_core.c (original) +++ branches/linux-2.4/ieee1394_core.c 2003-02-01 08:59:21.000000000 -0500 @@ -1218,3 +1218,15 @@ EXPORT_SYMBOL(ieee1394_devfs_handle); EXPORT_SYMBOL(ieee1394_procfs_entry); + +/** dma.c **/ +EXPORT_SYMBOL(dma_prog_region_init); +EXPORT_SYMBOL(dma_prog_region_alloc); +EXPORT_SYMBOL(dma_prog_region_free); +EXPORT_SYMBOL(dma_region_init); +EXPORT_SYMBOL(dma_region_alloc); +EXPORT_SYMBOL(dma_region_free); +EXPORT_SYMBOL(dma_region_sync); +EXPORT_SYMBOL(dma_region_mmap); +EXPORT_SYMBOL(dma_region_offset_to_bus); + |
From: SVN U. <dm...@li...> - 2003-02-01 13:59:52
|
Author: dmaas Date: 2003-01-10 20:50:20 -0500 (Fri, 10 Jan 2003) New Revision: 742 Modified: trunk/ohci1394.c Log: ohci1394 rawiso - clear multi-channel reception mask in recv_init(), not recv_start() Modified: trunk/ohci1394.c ============================================================================== --- trunk/ohci1394.c (original) +++ trunk/ohci1394.c 2003-02-01 08:59:19.000000000 -0500 @@ -1165,6 +1165,12 @@ recv->CommandPtr = OHCI1394_IsoRcvCommandPtr + 32 * ctx; recv->ContextMatch = OHCI1394_IsoRcvContextMatch + 32 * ctx; + if(iso->channel == -1) { + /* clear multi-channel selection mask */ + reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiClear, 0xFFFFFFFF); + reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoClear, 0xFFFFFFFF); + } + /* write the DMA program */ ohci_iso_recv_program(iso); @@ -1324,10 +1330,6 @@ if(iso->channel == -1) { /* enable multichannel reception */ reg_write(recv->ohci, recv->ContextControlSet, (1 << 28)); - - /* clear channel selection mask */ - reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiClear, 0xFFFFFFFF); - reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoClear, 0xFFFFFFFF); } else { /* listen on channel */ contextMatch |= iso->channel; |
From: SVN U. <dde...@li...> - 2003-02-01 13:59:50
|
Author: ddennedy Date: 2003-01-08 21:49:42 -0500 (Wed, 08 Jan 2003) New Revision: 741 Modified: branches/linux-2.4/dv1394.c Log: remove temporary comments Modified: branches/linux-2.4/dv1394.c ============================================================================== --- branches/linux-2.4/dv1394.c (original) +++ branches/linux-2.4/dv1394.c 2003-02-01 08:59:17.000000000 -0500 @@ -953,8 +953,8 @@ /* shutdown the card if it's currently active */ /* (the card should not be reset if the parameters are screwy) */ -// if( video_card_initialized(video) ) -// do_dv1394_shutdown(video, 0); + if( video_card_initialized(video) ) + do_dv1394_shutdown(video, 0); |
From: SVN U. <dde...@li...> - 2003-02-01 13:59:49
|
Author: ddennedy Date: 2003-01-07 22:31:25 -0500 (Tue, 07 Jan 2003) New Revision: 740 Added: branches/linux-2.4/dma.c branches/linux-2.4/dma.h Modified: branches/linux-2.4/Makefile branches/linux-2.4/dv1394-private.h branches/linux-2.4/dv1394.c Log: fix broken dv1394 receive mode and oops on module reload Modified: branches/linux-2.4/dv1394-private.h ============================================================================== --- branches/linux-2.4/dv1394-private.h (original) +++ branches/linux-2.4/dv1394-private.h 2003-02-01 08:59:16.000000000 -0500 @@ -28,8 +28,7 @@ #include "ieee1394.h" #include "ohci1394.h" -#include <linux/pci.h> -#include <asm/scatterlist.h> +#include "dma.h" /* data structures private to the dv1394 driver */ /* none of this is exposed to user-space */ @@ -167,12 +166,14 @@ } static inline void fill_input_last(struct input_last *il, + int want_interrupt, unsigned int data_size, unsigned long data_phys_addr) { u32 temp = 3 << 28; /* INPUT_LAST */ temp |= 8 << 24; /* s = 1, update xferStatus and resCount */ - temp |= 3 << 20; /* enable interrupts */ + if (want_interrupt) + temp |= 3 << 20; /* enable interrupts */ temp |= 0xC << 16; /* enable branch to address */ /* disable wait on sync field, not used in DV :-( */ temp |= data_size; @@ -301,8 +302,7 @@ unsigned long data; /* Max # of packets per frame */ - /* 320 is enough for NTSC, need to check what PAL is */ - #define MAX_PACKETS 500 +#define MAX_PACKETS 500 /* a PAGE_SIZE memory pool for allocating CIP headers @@ -383,35 +383,6 @@ /* reset f so that it can be used again */ static void frame_reset(struct frame *f); - -/* structure for bookkeeping of a large non-physically-contiguous DMA buffer */ - -struct dma_region { - unsigned int n_pages; - unsigned int n_dma_pages; - struct scatterlist *sglist; -}; - -/* return the DMA bus address of the byte with the given offset - relative to the beginning of the dma_region */ - -static inline dma_addr_t dma_offset_to_bus(struct dma_region *dma, unsigned long offset) -{ - int i; - struct scatterlist *sg; - - for(i = 0, sg = &dma->sglist[0]; i < dma->n_dma_pages; i++, sg++) { - if(offset < sg_dma_len(sg)) { - return sg_dma_address(sg) + offset; - } - offset -= sg_dma_len(sg); - } - - printk(KERN_ERR "dv1394: dma_offset_to_bus failed for offset %lu!\n", offset); - return 0; -} - - /* struct video_card contains all data associated with one instance of the dv1394 driver */ @@ -508,9 +479,8 @@ /* the large, non-contiguous (rvmalloc()) ringbuffer for DV data, exposed to user-space via mmap() */ - unsigned char *user_buf; - unsigned long user_buf_size; - struct dma_region user_dma; + unsigned long dv_buf_size; + struct dma_region dv_buf; /* next byte in the ringbuffer that a write() call will fill */ size_t write_off; @@ -579,10 +549,8 @@ /* physically contiguous packet ringbuffer for receive */ -#define MAX_PACKET_BUFFER 30 - struct packet *packet_buffer; - dma_addr_t packet_buffer_dma; - unsigned long packet_buffer_size; + struct dma_region packet_buf; + unsigned long packet_buf_size; unsigned int current_packet; int first_frame; /* received first start frame marker? */ Modified: branches/linux-2.4/Makefile ============================================================================== --- branches/linux-2.4/Makefile (original) +++ branches/linux-2.4/Makefile 2003-02-01 08:59:16.000000000 -0500 @@ -5,7 +5,7 @@ export-objs := ieee1394_core.o ohci1394.o cmp.o ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \ - highlevel.o csr.o nodemgr.o + highlevel.o csr.o nodemgr.o dma.o obj-$(CONFIG_IEEE1394) += ieee1394.o obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o Added: branches/linux-2.4/dma.c ============================================================================== --- branches/linux-2.4/dma.c (original) +++ branches/linux-2.4/dma.c 2003-02-01 08:59:16.000000000 -0500 @@ -0,0 +1,236 @@ +/* + * DMA region bookkeeping routines + * + * Copyright (C) 2002 Maas Digital LLC + * + * This code is licensed under the GPL. See the file COPYING in the root + * directory of the kernel sources for details. + */ + +#include <linux/module.h> +#include <linux/vmalloc.h> +#include <linux/slab.h> +#include "dma.h" + +/* dma_prog_region */ + +void dma_prog_region_init(struct dma_prog_region *prog) +{ + prog->kvirt = NULL; + prog->dev = NULL; + prog->n_pages = 0; + prog->bus_addr = 0; +} + +int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes, struct pci_dev *dev) +{ + /* round up to page size */ + n_bytes = round_up_to_page(n_bytes); + + prog->n_pages = n_bytes / PAGE_SIZE; + + prog->kvirt = pci_alloc_consistent(dev, prog->n_pages * PAGE_SIZE, &prog->bus_addr); + if(!prog->kvirt) { + printk(KERN_ERR "dma_prog_region_alloc: pci_alloc_consistent() failed\n"); + dma_prog_region_free(prog); + return -ENOMEM; + } + + prog->dev = dev; + + return 0; +} + +void dma_prog_region_free(struct dma_prog_region *prog) +{ + if(prog->kvirt) { + pci_free_consistent(prog->dev, prog->n_pages * PAGE_SIZE, prog->kvirt, prog->bus_addr); + } + + prog->kvirt = NULL; + prog->dev = NULL; + prog->n_pages = 0; + prog->bus_addr = 0; +} + +/* dma_region */ + +void dma_region_init(struct dma_region *dma) +{ + dma->kvirt = NULL; + dma->dev = NULL; + dma->n_pages = 0; + dma->n_dma_pages = 0; + dma->sglist = NULL; +} + +int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_dev *dev, int direction) +{ + unsigned int i, n_pages; + + /* round up to page size */ + n_bytes = round_up_to_page(n_bytes); + + n_pages = n_bytes / PAGE_SIZE; + + dma->kvirt = vmalloc_32(n_pages * PAGE_SIZE); + if(!dma->kvirt) { + printk(KERN_ERR "dma_region_alloc: vmalloc_32() failed\n"); + goto err; + } + + dma->n_pages = n_pages; + + /* Clear the ram out, no junk to the user */ + memset(dma->kvirt, 0, n_pages * PAGE_SIZE); + + /* allocate scatter/gather list */ + dma->sglist = kmalloc(dma->n_pages * sizeof(struct scatterlist), GFP_KERNEL); + if(!dma->sglist) { + printk(KERN_ERR "dma_region_alloc: kmalloc(sglist) failed\n"); + goto err; + } + + /* just to be safe - this will become unnecessary once sglist->address goes away */ + memset(dma->sglist, 0, dma->n_pages * sizeof(struct scatterlist)); + + /* fill scatter/gather list with pages */ + for(i = 0; i < dma->n_pages; i++) { + unsigned long va = (unsigned long) dma->kvirt + i * PAGE_SIZE; + + dma->sglist[i].page = vmalloc_to_page((void *)va); + dma->sglist[i].length = PAGE_SIZE; + } + + /* map sglist to the IOMMU */ + dma->n_dma_pages = pci_map_sg(dev, &dma->sglist[0], dma->n_pages, direction); + + if(dma->n_dma_pages == 0) { + printk(KERN_ERR "dma_region_alloc: pci_map_sg() failed\n"); + goto err; + } + + dma->dev = dev; + dma->direction = direction; + + return 0; + +err: + dma_region_free(dma); + return -ENOMEM; +} + +void dma_region_free(struct dma_region *dma) +{ + if(dma->n_dma_pages) { + pci_unmap_sg(dma->dev, dma->sglist, dma->n_pages, dma->direction); + dma->n_dma_pages = 0; + dma->dev = NULL; + } + + if(dma->sglist) { + kfree(dma->sglist); + dma->sglist = NULL; + } + + if(dma->kvirt) { + vfree(dma->kvirt); + dma->kvirt = NULL; + dma->n_pages = 0; + } +} + +/* find the scatterlist index and remaining offset corresponding to a + given offset from the beginning of the buffer */ +static inline int dma_region_find(struct dma_region *dma, unsigned long offset, unsigned long *rem) +{ + int i; + unsigned long off = offset; + + for(i = 0; i < dma->n_dma_pages; i++) { + if(off < sg_dma_len(&dma->sglist[i])) { + *rem = off; + return i; + } + + off -= sg_dma_len(&dma->sglist[i]); + } + + panic("dma_region_find: offset %lu beyond end of DMA mapping\n", offset); +} + +dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset) +{ + unsigned long rem; + + struct scatterlist *sg = &dma->sglist[dma_region_find(dma, offset, &rem)]; + return sg_dma_address(sg) + rem; +} + +void dma_region_sync(struct dma_region *dma, unsigned long offset, unsigned long len) +{ + int first, last; + unsigned long rem; + + if(!len) + len = 1; + + first = dma_region_find(dma, offset, &rem); + last = dma_region_find(dma, offset + len - 1, &rem); + + pci_dma_sync_sg(dma->dev, &dma->sglist[first], last - first + 1, dma->direction); +} + +/* nopage() handler for mmap access */ + +static struct page* +dma_region_pagefault(struct vm_area_struct *area, unsigned long address, int write_access) +{ + unsigned long offset; + unsigned long kernel_virt_addr; + struct page *ret = NOPAGE_SIGBUS; + + struct dma_region *dma = (struct dma_region*) area->vm_private_data; + + if(!dma->kvirt) + goto out; + + if( (address < (unsigned long) area->vm_start) || + (address > (unsigned long) area->vm_start + (PAGE_SIZE * dma->n_pages)) ) + goto out; + + offset = address - area->vm_start; + kernel_virt_addr = (unsigned long) dma->kvirt + offset; + ret = vmalloc_to_page((void*) kernel_virt_addr); + get_page(ret); +out: + return ret; +} + +static struct vm_operations_struct dma_region_vm_ops = { + .nopage = dma_region_pagefault, +}; + +int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_struct *vma) +{ + unsigned long size; + + if(!dma->kvirt) + return -EINVAL; + + /* must be page-aligned */ + if(vma->vm_pgoff != 0) + return -EINVAL; + + /* check the length */ + size = vma->vm_end - vma->vm_start; + if(size > (PAGE_SIZE * dma->n_pages)) + return -EINVAL; + + vma->vm_ops = &dma_region_vm_ops; + vma->vm_private_data = dma; + vma->vm_file = file; + vma->vm_flags |= VM_RESERVED; + + return 0; +} Added: branches/linux-2.4/dma.h ============================================================================== --- branches/linux-2.4/dma.h (original) +++ branches/linux-2.4/dma.h 2003-02-01 08:59:16.000000000 -0500 @@ -0,0 +1,84 @@ +/* + * DMA region bookkeeping routines + * + * Copyright (C) 2002 Maas Digital LLC + * + * This code is licensed under the GPL. See the file COPYING in the root + * directory of the kernel sources for details. + */ + +#ifndef IEEE1394_DMA_H +#define IEEE1394_DMA_H + +#include <linux/pci.h> +#include <asm/scatterlist.h> + +/* struct dma_prog_region + + a small, physically-contiguous DMA buffer with random-access, + synchronous usage characteristics +*/ + +struct dma_prog_region { + unsigned char *kvirt; /* kernel virtual address */ + struct pci_dev *dev; /* PCI device */ + unsigned int n_pages; /* # of kernel pages */ + dma_addr_t bus_addr; /* base bus address */ +}; + +/* clear out all fields but do not allocate any memory */ +void dma_prog_region_init(struct dma_prog_region *prog); +int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes, struct pci_dev *dev); +void dma_prog_region_free(struct dma_prog_region *prog); + +static inline dma_addr_t dma_prog_region_offset_to_bus(struct dma_prog_region *prog, unsigned long offset) +{ + return prog->bus_addr + offset; +} + +/* struct dma_region + + a large, non-physically-contiguous DMA buffer with streaming, + asynchronous usage characteristics +*/ + +struct dma_region { + unsigned char *kvirt; /* kernel virtual address */ + struct pci_dev *dev; /* PCI device */ + unsigned int n_pages; /* # of kernel pages */ + unsigned int n_dma_pages; /* # of IOMMU pages */ + struct scatterlist *sglist; /* IOMMU mapping */ + int direction; /* PCI_DMA_TODEVICE, etc */ +}; + +/* clear out all fields but do not allocate anything */ +void dma_region_init(struct dma_region *dma); + +/* allocate the buffer and map it to the IOMMU */ +int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_dev *dev, int direction); + +/* unmap and free the buffer */ +void dma_region_free(struct dma_region *dma); + +/* sync the IO bus' view of the buffer with the CPU's view */ +void dma_region_sync(struct dma_region *dma, unsigned long offset, unsigned long len); + +/* map the buffer into a user space process */ +int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_struct *vma); + +/* macro to index into a DMA region (or dma_prog_region) */ +#define dma_region_i(_dma, _type, _index) ( ((_type*) ((_dma)->kvirt)) + (_index) ) + +/* return the DMA bus address of the byte with the given offset + relative to the beginning of the dma_region */ +dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset); + +/* round up a number of bytes to be a multiple of the PAGE_SIZE */ +static inline unsigned long round_up_to_page(unsigned long len) +{ + if(len % PAGE_SIZE) + len += PAGE_SIZE - (len % PAGE_SIZE); + return len; +} + +#endif /* IEEE1394_DMA_H */ Modified: branches/linux-2.4/dv1394.c ============================================================================== --- branches/linux-2.4/dv1394.c (original) +++ branches/linux-2.4/dv1394.c 2003-02-01 08:59:16.000000000 -0500 @@ -53,6 +53,12 @@ via pci_alloc_consistent() DONE: + - during reception, better handling of dropped frames and continuity errors + - during reception, prevent DMA from bypassing the irq tasklets + - reduce irq rate during reception (1/250 packets). + - add many more internal buffers during reception with scatter/gather dma. + - add dbc (continuity) checking on receive, increment status.dropped_frames + if not continuous. - restart IT DMA after a bus reset - safely obtain and release ISO Tx channels in cooperation with OHCI driver - map received DIF blocks to their proper location in DV frame (ensure @@ -91,9 +97,9 @@ #include <linux/fs.h> #include <linux/poll.h> #include <linux/smp_lock.h> +#include <linux/bitops.h> #include <asm/byteorder.h> #include <asm/atomic.h> -#include <asm/bitops.h> #include <asm/io.h> #include <asm/uaccess.h> #include <linux/proc_fs.h> @@ -132,7 +138,7 @@ (will cause undeflows if your machine is too slow!) */ -#define DV1394_DEBUG_LEVEL 0 +#define DV1394_DEBUG_LEVEL 1 /* for debugging use ONLY: allow more than one open() of the device */ /* #define DV1394_ALLOW_MORE_THAN_ONE_OPEN 1 */ @@ -185,39 +191,6 @@ return (struct video_card*) file->private_data; } - -/*******************************/ -/* Memory management functions */ -/*******************************/ - -/* note: we no longer use mem_map_reserve, because it causes a memory - leak, and setting vma->vm_flags to VM_RESERVED should be sufficient - to pin the pages in memory anyway. */ - -static void * rvmalloc(unsigned long size) -{ - void * mem; - - mem = vmalloc_32(size); - - if(mem) - memset(mem, 0, size); /* Clear the ram out, - no junk to the user */ - return mem; -} - -static void rvfree(void * mem, unsigned long size) -{ - if (mem) { - vfree(mem); - } -} - -/***********************************/ -/* END Memory management functions */ -/***********************************/ - - /*** FRAME METHODS *********************************************************/ static void frame_reset(struct frame *f) @@ -446,11 +419,7 @@ /******************************/ /* first descriptor - OUTPUT_MORE_IMMEDIATE, for the controller's IT header */ - fill_output_more_immediate( &(block->u.out.omi), - /* tag - what is this??? */ 1, - video->channel, - /* sync tag - what is this??? */ 0, - payload_size); + fill_output_more_immediate( &(block->u.out.omi), 1, video->channel, 0, payload_size); if(empty_packet) { /* second descriptor - OUTPUT_LAST for CIP header */ @@ -501,8 +470,8 @@ PAGE_SIZE - (data_p % PAGE_SIZE), /* DMA address of data_p */ - dma_offset_to_bus(&f->video->user_dma, - data_p - (unsigned long) f->video->user_buf)); + dma_region_offset_to_bus(&video->dv_buf, + data_p - (unsigned long) video->dv_buf.kvirt)); fill_output_last( &(block->u.out.u.full.u.cross.ol), @@ -516,8 +485,8 @@ 480 - (PAGE_SIZE - (data_p % PAGE_SIZE)), /* DMA address of data_p + PAGE_SIZE - (data_p % PAGE_SIZE) */ - dma_offset_to_bus(&f->video->user_dma, - data_p + PAGE_SIZE - (data_p % PAGE_SIZE) - (unsigned long) f->video->user_buf)); + dma_region_offset_to_bus(&video->dv_buf, + data_p + PAGE_SIZE - (data_p % PAGE_SIZE) - (unsigned long) video->dv_buf.kvirt)); if(first_packet) f->frame_begin_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]); @@ -551,8 +520,8 @@ /* DMA address of data_p */ - dma_offset_to_bus(&f->video->user_dma, - data_p - (unsigned long) f->video->user_buf)); + dma_region_offset_to_bus(&video->dv_buf, + data_p - (unsigned long) video->dv_buf.kvirt)); if(first_packet) f->frame_begin_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]); @@ -593,13 +562,8 @@ to loop back up to the top */ *(f->frame_end_branch) = cpu_to_le32(f->descriptor_pool_dma | f->first_n_descriptors); - - /* make the latest version of the frame buffer visible to the PCI card */ - /* could optimize this by only syncing the pages associated with this frame */ - pci_dma_sync_sg(video->ohci->dev, - &video->user_dma.sglist[0], - video->user_dma.n_dma_pages, - PCI_DMA_TODEVICE); + /* make the latest version of this frame visible to the PCI card */ + dma_region_sync(&video->dv_buf, f->data - (unsigned long) video->dv_buf.kvirt, video->frame_size); /* lock against DMA interrupt */ spin_lock_irqsave(&video->spinlock, irq_flags); @@ -798,6 +762,9 @@ int dif_sequence = p->data[1] >> 4; /* dif sequence number is in bits 4 - 7 */ int dif_block = p->data[2]; + /* sanity check */ + if (dif_sequence > 11 || dif_block > 149) return; + switch (section_type) { case 0: /* 1 Header block */ memcpy( (void *) f->data + dif_sequence * 150 * 80, p->data, 480); @@ -825,47 +792,64 @@ } -static void start_dma_receive(struct video_card *video, struct frame *frame) +static void start_dma_receive(struct video_card *video) { - /* reset iso recv control register */ - reg_write(video->ohci, video->ohci_IsoRcvContextControlClear, 0xFFFFFFFF); - wmb(); - - /* clear bufferFill, set isochHeader and speed (0=100) */ - reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x40000000); - - /* match on all tags, listen on channel */ - reg_write(video->ohci, video->ohci_IsoRcvContextMatch, 0xf0000000 | video->channel); - - /* address and first descriptor block + Z=1 */ - reg_write(video->ohci, video->ohci_IsoRcvCommandPtr, - frame->descriptor_pool_dma | 1); /* Z=1 */ - wmb(); + if (video->first_run == 1) { + video->first_run = 0; + + /* start DMA once all of the frames are READY */ + video->n_clear_frames = 0; + video->first_clear_frame = -1; + video->current_packet = 0; + video->active_frame = 0; + + /* reset iso recv control register */ + reg_write(video->ohci, video->ohci_IsoRcvContextControlClear, 0xFFFFFFFF); + wmb(); + + /* clear bufferFill, set isochHeader and speed (0=100) */ + reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x40000000); - /* run */ - reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x8000); - flush_pci_write(video->ohci); + /* match on all tags, listen on channel */ + reg_write(video->ohci, video->ohci_IsoRcvContextMatch, 0xf0000000 | video->channel); + + /* address and first descriptor block + Z=1 */ + reg_write(video->ohci, video->ohci_IsoRcvCommandPtr, + video->frames[0]->descriptor_pool_dma | 1); /* Z=1 */ + wmb(); + + /* run */ + reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x8000); + flush_pci_write(video->ohci); + + debug_printk("dv1394: DMA started\n"); - debug_printk("dv1394: DMA started\n"); - #if DV1394_DEBUG_LEVEL >= 2 - { - int i; - - for(i = 0; i < 1000; ++i) { - mdelay(1); - if(reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) { - printk("DMA ACTIVE after %d msec\n", i); - break; + { + int i; + + for(i = 0; i < 1000; ++i) { + mdelay(1); + if(reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) { + printk("DMA ACTIVE after %d msec\n", i); + break; + } } + if( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 11) ) { + printk("DEAD, event = %x\n", + reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F); + } else + printk("RUNNING!\n"); } - if( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 11) ) { - printk("DEAD, event = %x\n", - reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F); - } else - printk("RUNNING!\n"); - } #endif + } + else if( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 11) ) { + debug_printk("DEAD, event = %x\n", + reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F); + + /* wake */ + reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12)); + } } @@ -873,7 +857,7 @@ receive_packets() - build the DMA program for receiving */ -static void receive_packets(struct video_card *video, struct frame *f) +static void receive_packets(struct video_card *video) { struct DMA_descriptor_block *block = NULL; dma_addr_t block_dma = 0; @@ -881,52 +865,46 @@ dma_addr_t data_dma = 0; u32 *last_branch_address = NULL; unsigned long irq_flags; + int want_interrupt = 0; + struct frame *f = NULL; + int i, j; spin_lock_irqsave(&video->spinlock, irq_flags); - video->n_clear_frames = 0; - video->first_clear_frame = -1; + for (j = 0; j < video->n_frames; j++) { - for (video->current_packet = 0; video->current_packet < MAX_PACKET_BUFFER; ++video->current_packet) { - /* locate a descriptor block and packet from the buffer */ - block = &(f->descriptor_pool[video->current_packet]); - block_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma; - - data = &(video->packet_buffer[video->current_packet]); - data_dma = ((unsigned long) data - (unsigned long) video->packet_buffer) + video->packet_buffer_dma; - - /* setup DMA descriptor block */ - fill_input_last( &(block->u.in.il), 512, data_dma); - - /* link descriptors */ - last_branch_address = f->frame_end_branch; + /* connect frames */ + if (j > 0 && f != NULL && f->frame_end_branch != NULL) + *(f->frame_end_branch) = cpu_to_le32(video->frames[j]->descriptor_pool_dma | 1); /* set Z=1 */ - if (last_branch_address) - *(last_branch_address) = cpu_to_le32(block_dma | 1); /* set Z=1 */ + f = video->frames[j]; - f->frame_end_branch = &(block->u.in.il.q[2]); - } + for (i = 0; i < MAX_PACKETS; i++) { + /* locate a descriptor block and packet from the buffer */ + block = &(f->descriptor_pool[i]); + block_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma; + + data = ((struct packet*)video->packet_buf.kvirt) + f->frame_num * MAX_PACKETS + i; + data_dma = dma_region_offset_to_bus( &video->packet_buf, + ((unsigned long) data - (unsigned long) video->packet_buf.kvirt) ); + + /* setup DMA descriptor block */ + want_interrupt = ((i % (MAX_PACKETS/2)) == 0 || i == (MAX_PACKETS-1)); + fill_input_last( &(block->u.in.il), want_interrupt, 512, data_dma); + + /* link descriptors */ + last_branch_address = f->frame_end_branch; + + if (last_branch_address != NULL) + *(last_branch_address) = cpu_to_le32(block_dma | 1); /* set Z=1 */ + + f->frame_end_branch = &(block->u.in.il.q[2]); + } - /* loop tail to head */ - if (f->frame_end_branch) - *(f->frame_end_branch) = cpu_to_le32(f->descriptor_pool_dma | 1); /* set Z=1 */ + } /* next j */ spin_unlock_irqrestore(&video->spinlock, irq_flags); - if (video->first_run) { - /* start DMA once all of the frames are READY */ - video->first_run = 0; - video->current_packet = 0; - video->active_frame = f->frame_num; - start_dma_receive(video, f); - } - else if( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 11) ) { - debug_printk("DEAD, event = %x\n", - reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F); - - /* wake */ - reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12)); - } } @@ -940,6 +918,7 @@ u64 chan_mask; int retval = -EINVAL; + debug_printk( "dv1394: initialising %d\n", video->id ); if(init->api_version != DV1394_API_VERSION) goto err; @@ -969,15 +948,13 @@ if(new_buf_size % PAGE_SIZE) new_buf_size += PAGE_SIZE - (new_buf_size % PAGE_SIZE); /* don't allow the user to allocate the DMA buffer more than once */ - if( (video->user_buf) && - (video->user_buf_size != new_buf_size) ) { + if(video->dv_buf.kvirt && video->dv_buf_size != new_buf_size) goto err; - } /* shutdown the card if it's currently active */ /* (the card should not be reset if the parameters are screwy) */ - if( video_card_initialized(video) ) - do_dv1394_shutdown(video, 0); +// if( video_card_initialized(video) ) +// do_dv1394_shutdown(video, 0); @@ -1076,93 +1053,39 @@ } } - - - if(video->user_buf == NULL) { - unsigned int i; - + if(!video->dv_buf.kvirt) { /* allocate the ringbuffer */ - video->user_buf = rvmalloc(new_buf_size); - if(!video->user_buf) { - printk(KERN_ERR "dv1394: Cannot allocate frame buffers\n"); + retval = dma_region_alloc(&video->dv_buf, new_buf_size, video->ohci->dev, PCI_DMA_TODEVICE); + if(retval) goto err_frames; - } - video->user_buf_size = new_buf_size; - - /* allocate the sglist to hold the DMA addresses */ - video->user_dma.n_pages = video->user_buf_size / PAGE_SIZE; - video->user_dma.sglist = kmalloc(video->user_dma.n_pages * sizeof(struct scatterlist), GFP_KERNEL); - if(!video->user_dma.sglist) { - printk(KERN_ERR "dv1394: Cannot allocate sglist for user buffer\n"); - goto err_user_buf; - } - - /* initialize all fields of all sglist entries to zero - (new requirement due to PCI changes in 2.4.13) */ - - memset(video->user_dma.sglist, 0, video->user_dma.n_pages * sizeof(struct scatterlist)); + + video->dv_buf_size = new_buf_size; - - /* fill the sglist with the kernel addresses of pages in the non-contiguous buffer */ - for(i = 0; i < video->user_dma.n_pages; i++) { - unsigned long va = (unsigned long) video->user_buf + i * PAGE_SIZE; - - video->user_dma.sglist[i].page = vmalloc_to_page((void *)va); - video->user_dma.sglist[i].length = PAGE_SIZE; - } - - /* map the buffer in the IOMMU */ - /* the user_data buffer only allows DMA *to* the card for transmission; - incoming DV data comes through the packet_buffer first, and then is copied to user_data */ - video->user_dma.n_dma_pages = pci_map_sg(video->ohci->dev, - &video->user_dma.sglist[0], - video->user_dma.n_pages, - PCI_DMA_TODEVICE); - if(video->user_dma.n_dma_pages == 0) { - printk(KERN_ERR "dv1394: Error mapping user buffer to the IOMMU\n"); - goto err_user_buf; - } - debug_printk("dv1394: Allocated %d frame buffers, total %u pages (%u DMA pages), %lu bytes\n", - video->n_frames, video->user_dma.n_pages, - video->user_dma.n_dma_pages, video->user_buf_size); + video->n_frames, video->dv_buf.n_pages, + video->dv_buf.n_dma_pages, video->dv_buf_size); } /* set up the frame->data pointers */ for(i = 0; i < video->n_frames; i++) - video->frames[i]->data = (unsigned long) video->user_buf + i * video->frame_size; - - /* allocate packet buffers */ - video->packet_buffer_size = sizeof(struct packet) * MAX_PACKET_BUFFER; - if (video->packet_buffer_size % PAGE_SIZE) - video->packet_buffer_size += PAGE_SIZE - (video->packet_buffer_size % PAGE_SIZE); - - - video->packet_buffer = kmalloc(video->packet_buffer_size, GFP_KERNEL); - - if(!video->packet_buffer) { - printk(KERN_ERR "dv1394: Cannot allocate packet buffers"); - retval = -ENOMEM; - goto err_user_buf; - } + video->frames[i]->data = (unsigned long) video->dv_buf.kvirt + i * video->frame_size; - /* map the packet buffer into the IOMMU */ - video->packet_buffer_dma = pci_map_single(video->ohci->dev, - video->packet_buffer, - video->packet_buffer_size, - PCI_DMA_FROMDEVICE); - if(!video->packet_buffer_dma) { - printk(KERN_ERR "dv1394: Cannot map packet buffer to IOMMU"); - kfree(video->packet_buffer); - video->packet_buffer = NULL; - retval = -ENOMEM; - goto err_user_buf; + if(!video->packet_buf.kvirt) { + /* allocate packet buffer */ + video->packet_buf_size = sizeof(struct packet) * video->n_frames * MAX_PACKETS; + if (video->packet_buf_size % PAGE_SIZE) + video->packet_buf_size += PAGE_SIZE - (video->packet_buf_size % PAGE_SIZE); + + retval = dma_region_alloc(&video->packet_buf, video->packet_buf_size, + video->ohci->dev, PCI_DMA_FROMDEVICE); + if(retval) + goto err_dv_buf; + + debug_printk("dv1394: Allocated %d packets in buffer, total %u pages (%u DMA pages), %lu bytes\n", + video->n_frames*MAX_PACKETS, video->packet_buf.n_pages, + video->packet_buf.n_dma_pages, video->packet_buf_size); } - - debug_printk("dv1394: Allocated %d packet buffers for receive, total %lu bytes\n", - MAX_PACKET_BUFFER, video->packet_buffer_size); - - + /* set up register offsets for IT context */ /* IT DMA context registers are spaced 16 bytes apart */ video->ohci_IsoXmitContextControlSet = OHCI1394_IsoXmitContextControlSet+16*video->ohci_it_ctx; @@ -1186,26 +1109,9 @@ return 0; - err_user_buf: - if(video->user_buf) { - if(video->user_dma.sglist) { - if(video->user_dma.n_dma_pages > 0) { - /* unmap it from the IOMMU */ - pci_unmap_sg(video->ohci->dev, - video->user_dma.sglist, - video->user_dma.n_pages, - PCI_DMA_TODEVICE); - video->user_dma.n_dma_pages = 0; - } - kfree(video->user_dma.sglist); - video->user_dma.sglist = NULL; - video->user_dma.n_pages = 0; - } - rvfree(video->user_buf, video->user_buf_size); - video->user_buf = NULL; - video->user_buf_size = 0; - } - + err_dv_buf: + dma_region_free(&video->dv_buf); + err_frames: for(i = 0; i < DV1394_MAX_FRAMES; i++) { if(video->frames[i]) @@ -1238,7 +1144,7 @@ struct dv1394_init init; init.api_version = DV1394_API_VERSION; - init.n_frames = 2; + init.n_frames = DV1394_MAX_FRAMES / 4; /* the following are now set via proc_fs or devfs */ init.channel = video->channel; init.format = video->pal_or_ntsc; @@ -1270,7 +1176,6 @@ video->active_frame = -1; video->first_run = 1; - /* wait until DMA really stops */ i = 0; @@ -1282,6 +1187,7 @@ if( (reg_read(video->ohci, video->ohci_IsoXmitContextControlClear) & (1 << 10)) || (reg_read(video->ohci, video->ohci_IsoRcvContextControlClear) & (1 << 10)) ) { /* still active */ + debug_printk("dv1394: stop_dma: DMA not stopped yet\n" ); mb(); } else { debug_printk("dv1394: stop_dma: DMA stopped safely after %d ms\n", i/10); @@ -1295,13 +1201,15 @@ printk(KERN_ERR "dv1394: stop_dma: DMA still going after %d ms!\n", i/10); } } - + else + debug_printk("dv1394: stop_dma: already stopped.\n"); + spin_unlock_irqrestore(&video->spinlock, flags); } -static int do_dv1394_shutdown(struct video_card *video, int free_user_buf) +static int do_dv1394_shutdown(struct video_card *video, int free_dv_buf) { int i; unsigned long flags; @@ -1322,7 +1230,8 @@ /* disable interrupts for IT context */ reg_write(video->ohci, OHCI1394_IsoXmitIntMaskClear, (1 << video->ohci_it_ctx)); - clear_bit(video->ohci_it_ctx, &video->ohci->it_ctx_usage); + /* remove tasklet */ + ohci1394_unregister_iso_tasklet(video->ohci, &video->it_tasklet); debug_printk("dv1394: IT context %d released\n", video->ohci_it_ctx); video->ohci_it_ctx = -1; } @@ -1336,13 +1245,14 @@ /* disable interrupts for IR context */ reg_write(video->ohci, OHCI1394_IsoRecvIntMaskClear, (1 << video->ohci_ir_ctx)); - clear_bit(video->ohci_ir_ctx, &video->ohci->ir_ctx_usage); + /* remove tasklet */ + ohci1394_unregister_iso_tasklet(video->ohci, &video->ir_tasklet); debug_printk("dv1394: IR context %d released\n", video->ohci_ir_ctx); video->ohci_ir_ctx = -1; } spin_unlock_irqrestore(&video->spinlock, flags); - + /* release the ISO channel */ if(video->channel != -1) { u64 chan_mask; @@ -1369,42 +1279,20 @@ /* we can't free the DMA buffer unless it is guaranteed that no more user-space mappings exist */ - if(free_user_buf && video->user_buf) { - if(video->user_dma.sglist) { - if(video->user_dma.n_dma_pages > 0) { - /* unmap it from the IOMMU */ - pci_unmap_sg(video->ohci->dev, - video->user_dma.sglist, - video->user_dma.n_pages, - PCI_DMA_TODEVICE); - video->user_dma.n_dma_pages = 0; - } - kfree(video->user_dma.sglist); - video->user_dma.sglist = NULL; - video->user_dma.n_pages = 0; - } - rvfree(video->user_buf, video->user_buf_size); - video->user_buf = NULL; - video->user_buf_size = 0; - } - - if (video->packet_buffer) { - pci_unmap_single(video->ohci->dev, - video->packet_buffer_dma, - video->packet_buffer_size, - PCI_DMA_FROMDEVICE); - kfree(video->packet_buffer); - video->packet_buffer = NULL; - video->packet_buffer_size = 0; + if(free_dv_buf) { + dma_region_free(&video->dv_buf); + video->dv_buf_size = 0; } + /* free packet buffer */ + dma_region_free(&video->packet_buf); + video->packet_buf_size = 0; + debug_printk("dv1394: shutdown complete\n"); return 0; } - - /* ********************************** *** MMAP() THEORY OF OPERATION *** @@ -1427,96 +1315,28 @@ force the user to choose one buffer size and stick with it. This small sacrifice is worth the huge reduction in error-prone code in dv1394. - - Note: dv1394_mmap does no page table manipulation. The page - table entries are created by the dv1394_nopage() handler as - page faults are taken by the user. -*/ - -static struct page * dv1394_nopage(struct vm_area_struct * area, unsigned long address, int write_access) -{ - unsigned long offset; - unsigned long kernel_virt_addr; - struct page *ret = NOPAGE_SIGBUS; - - struct video_card *video = (struct video_card*) area->vm_private_data; - - /* guard against process-context operations and the interrupt */ - /* (by definition page faults are taken in interrupt context) */ - spin_lock(&video->spinlock); - - if(!video->user_buf) - goto out; - - if( (address < (unsigned long) area->vm_start) || - (address > (unsigned long) area->vm_start + video->user_buf_size) ) - goto out; - - offset = address - area->vm_start; - kernel_virt_addr = (unsigned long) video->user_buf + offset; - ret = vmalloc_to_page((void *)kernel_virt_addr); - get_page(ret); - - out: - spin_unlock(&video->spinlock); - return ret; -} - -static struct vm_operations_struct dv1394_vm_ops = { - .nopage = dv1394_nopage -}; - -/* - dv1394_mmap does no page table manipulation. The page table entries - are created by the dv1394_nopage() handler as page faults are taken - by the user. */ int dv1394_mmap(struct file *file, struct vm_area_struct *vma) { struct video_card *video = file_to_video_card(file); - unsigned long size; - int res = -EINVAL; + int retval = -EINVAL; /* serialize mmap */ down(&video->sem); if( ! video_card_initialized(video) ) { - res = do_dv1394_init_default(video); - if(res) - goto err; + retval = do_dv1394_init_default(video); + if(retval) + goto out; } - /* region must be page-aligned */ - if(vma->vm_pgoff != 0) - goto err; - - /* check the size the user is trying to map */ - size = vma->vm_end - vma->vm_start; - if(size > video->user_buf_size) - goto err; - - /* - we don't actually mess with the page tables here. - (nopage() takes care of that from the page fault handler) - Just set up the vma->vm_ops. - */ - - vma->vm_ops = &dv1394_vm_ops; - vma->vm_private_data = video; - vma->vm_file = file; - - /* don't try to swap this out =) */ - vma->vm_flags |= VM_RESERVED; - - up(&video->sem); - return 0; - err: + retval = dma_region_mmap(&video->dv_buf, file, vma); +out: up(&video->sem); - return res; + return retval; } - /*** DEVICE FILE INTERFACE *************************************************/ /* no need to serialize, multiple threads OK */ @@ -1632,7 +1452,7 @@ continue; /* start over from 'while(count > 0)...' */ } - if(copy_from_user(video->user_buf + video->write_off, buffer, cnt)) { + if(copy_from_user(video->dv_buf.kvirt + video->write_off, buffer, cnt)) { if(!ret) ret = -EFAULT; break; @@ -1679,7 +1499,11 @@ up(&video->sem); return ret; } - receive_packets(video, video->frames[video->first_clear_frame]); + video->continuity_counter = -1; + + receive_packets(video); + + start_dma_receive(video); } ret = 0; @@ -1732,7 +1556,7 @@ continue; /* start over from 'while(count > 0)...' */ } - if(copy_to_user(buffer, video->user_buf + video->write_off, cnt)) { + if(copy_to_user(buffer, video->dv_buf.kvirt + video->write_off, cnt)) { if(!ret) ret = -EFAULT; break; @@ -1921,14 +1745,17 @@ } case DV1394_START_RECEIVE: { - if( !video_card_initialized(video) ) { ret = do_dv1394_init_default(video); if(ret) goto out; } - receive_packets(video, video->frames[video->first_clear_frame]); + video->continuity_counter = -1; + + receive_packets(video); + + start_dma_receive(video); ret = 0; break; @@ -2026,7 +1853,7 @@ struct video_card *p; list_for_each(lh, &dv1394_cards) { p = list_entry(lh, struct video_card, list); - if((p->id >> 2) == ieee1394_file_to_instance(file)) { + if((p->id) == ieee1394_file_to_instance(file)) { video = p; break; } @@ -2318,9 +2145,7 @@ struct video_card *video = (struct video_card*) data; spin_lock(&video->spinlock); - - irq_printk("INTERRUPT! Video = %08lx Iso event Recv: %08x Xmit: %08x\n", - (unsigned long) video, isoRecvIntEvent, isoXmitIntEvent); + irq_printk("ContextControl = %08x, CommandPtr = %08x\n", reg_read(video->ohci, video->ohci_IsoXmitContextControlSet), reg_read(video->ohci, video->ohci_IsoXmitCommandPtr) @@ -2462,82 +2287,149 @@ int wake = 0; struct video_card *video = (struct video_card*) data; - if( (video->ohci_ir_ctx != -1) && - (reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) ) { + spin_lock(&video->spinlock); + + if( (video->ohci_ir_ctx != -1) + && (reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) ) + { int sof=0; /* start-of-frame flag */ struct frame *f; u16 packet_length, packet_time; - - packet_length = le16_to_cpu(video->packet_buffer[video->current_packet].data_length); - packet_time = le16_to_cpu(video->packet_buffer[video->current_packet].timestamp); - - irq_printk("received packet %02d, timestamp=%04x, length=%04x, sof=%02x%02x\n", video->current_packet, - packet_time, packet_length, - video->packet_buffer[video->current_packet].data[0], video->packet_buffer[video->current_packet].data[1]); - - f = video->frames[video->active_frame]; - - /* exclude empty packet */ - if (packet_length > 8) { - - /* check for start of frame */ - sof = (video->packet_buffer[video->current_packet].data[0] == 0x1f && - video->packet_buffer[video->current_packet].data[1] == 0x07); - - if (!video->first_frame) { - if (sof) { - video->first_frame = 1; - } - - } else if (sof) { - /* close current frame */ - frame_reset(f); /* f->state = STATE_CLEAR */ - video->n_clear_frames++; - if (video->n_clear_frames > video->n_frames) { - video->n_clear_frames = video->n_frames; - video->dropped_frames++; - } - if (video->first_clear_frame == -1) - video->first_clear_frame = video->active_frame; - - /* get the next frame */ - video->active_frame = (video->active_frame + 1) % video->n_frames; - f = video->frames[video->active_frame]; - - irq_printk(" frame received, active_frame = %d, n_clear_frames = %d, first_clear_frame = %d\n", - video->active_frame, video->n_clear_frames, video->first_clear_frame); - } - if (video->first_frame) { - if (sof) { - /* open next frame */ - f->state = FRAME_READY; + int i, dbc=0; + struct DMA_descriptor_block *block = NULL; + u16 xferstatus; + + int next_i, prev_i; + struct DMA_descriptor_block *next = NULL; + dma_addr_t next_dma = 0; + struct DMA_descriptor_block *prev = NULL; + + /* loop over all descriptors in all frames */ + for (i = 0; i < video->n_frames*MAX_PACKETS; i++) { + struct packet *p = dma_region_i(&video->packet_buf, struct packet, video->current_packet); + + /* make sure we are seeing the latest changes to p */ + dma_region_sync(&video->packet_buf, + (unsigned long) p - (unsigned long) video->packet_buf.kvirt, + sizeof(struct packet)); + + packet_length = le16_to_cpu(p->data_length); + packet_time = le16_to_cpu(p->timestamp); + + irq_printk("received packet %02d, timestamp=%04x, length=%04x, sof=%02x%02x\n", video->current_packet, + packet_time, packet_length, + p->data[0], p->data[1]); + + /* get the descriptor based on packet_buffer cursor */ + f = video->frames[video->current_packet / MAX_PACKETS]; + block = &(f->descriptor_pool[video->current_packet % MAX_PACKETS]); + xferstatus = le16_to_cpu(block->u.in.il.q[3] >> 16); + xferstatus &= 0x1F; + + /* get the current frame */ + f = video->frames[video->active_frame]; + + /* exclude empty packet */ + if (packet_length > 8 && xferstatus == 0x11) { + irq_printk("ir_tasklet_func: xferStatus/resCount [%d] = 0x%08x\n", i, le32_to_cpu(block->u.in.il.q[3]) ); + + /* check for start of frame */ + /* DRD> Changed to check section type ([0]>>5==0) + and dif sequence ([1]>>4==0) */ + sof = ( (p->data[0] >> 5) == 0 && (p->data[1] >> 4) == 0); + + dbc = (int) (p->cip_h1 >> 24); + if ( video->continuity_counter != -1 && dbc > ((video->continuity_counter + 1) % 256) ) + { + printk(KERN_WARNING "dv1394: discontinuity detected, dropping all frames\n" ); + video->dropped_frames += video->n_clear_frames + 1; + video->first_frame = 0; + video->n_clear_frames = 0; + video->first_clear_frame = -1; } + video->continuity_counter = dbc; - /* copy to buffer */ - if (f->n_packets > (video->frame_size / 480)) { - printk(KERN_ERR "frame buffer overflow during receive\n"); + if (!video->first_frame) { + if (sof) { + video->first_frame = 1; + } + + } else if (sof) { + /* close current frame */ + frame_reset(f); /* f->state = STATE_CLEAR */ + video->n_clear_frames++; + if (video->n_clear_frames > video->n_frames) { + video->dropped_frames++; + printk(KERN_WARNING "dv1394: dropped a frame during reception\n" ); + video->n_clear_frames = video->n_frames-1; + video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames; + } + if (video->first_clear_frame == -1) + video->first_clear_frame = video->active_frame; + + /* get the next frame */ + video->active_frame = (video->active_frame + 1) % video->n_frames; + f = video->frames[video->active_frame]; + irq_printk(" frame received, active_frame = %d, n_clear_frames = %d, first_clear_frame = %d\n", + video->active_frame, video->n_clear_frames, video->first_clear_frame); } + if (video->first_frame) { + if (sof) { + /* open next frame */ + f->state = FRAME_READY; + } + + /* copy to buffer */ + if (f->n_packets > (video->frame_size / 480)) { + printk(KERN_ERR "frame buffer overflow during receive\n"); + } + + frame_put_packet(f, p); + + } /* first_frame */ + } + + /* stop, end of ready packets */ + else if (xferstatus == 0) { + break; + } + + /* reset xferStatus & resCount */ + block->u.in.il.q[3] = cpu_to_le32(512); - /* make sure we are seeing the latest changes to packet_buffer */ - pci_dma_sync_single(video->ohci->dev, - video->packet_buffer_dma, - video->packet_buffer_size, - PCI_DMA_FROMDEVICE); - - frame_put_packet( f, &video->packet_buffer[video->current_packet]); - - } /* first_frame */ - - } /* not empty packet */ - - /* advance packet_buffer cursor */ - video->current_packet = (video->current_packet + 1) % MAX_PACKET_BUFFER; + /* terminate dma chain at this (next) packet */ + next_i = video->current_packet; + f = video->frames[next_i / MAX_PACKETS]; + next = &(f->descriptor_pool[next_i % MAX_PACKETS]); + next_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma; + next->u.in.il.q[0] |= 3 << 20; /* enable interrupt */ + next->u.in.il.q[2] = 0; /* disable branch */ + + /* link previous to next */ + prev_i = (next_i == 0) ? (MAX_PACKETS * video->n_frames - 1) : (next_i - 1); + f = video->frames[prev_i / MAX_PACKETS]; + prev = &(f->descriptor_pool[prev_i % MAX_PACKETS]); + if(prev_i % (MAX_PACKETS/2)) { + prev->u.in.il.q[0] &= ~(3 << 20); /* no interrupt */ + } else { + prev->u.in.il.q[0] |= 3 << 20; /* enable interrupt */ + } + prev->u.in.il.q[2] = (cpu_to_le32(next_dma) | 1); /* set Z=1 */ + wmb(); + + /* wake up DMA in case it fell asleep */ + reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12)); + + /* advance packet_buffer cursor */ + video->current_packet = (video->current_packet + 1) % (MAX_PACKETS * video->n_frames); + + } /* for all packets */ wake = 1; /* why the hell not? */ - + } /* receive interrupt */ - + spin_unlock(&video->spinlock); if(wake) { @@ -2716,6 +2608,10 @@ /* lower 2 bits of id indicate which of four "plugs" per host */ video->id = ohci->id << 2; + if (format == DV1394_NTSC) + video->id |= mode; + else + video->id |= 2 + mode; video->ohci_it_ctx = -1; video->ohci_ir_ctx = -1; @@ -2748,8 +2644,10 @@ for(i = 0; i < DV1394_MAX_FRAMES; i++) video->frames[i] = NULL; - video->user_buf = NULL; - video->user_buf_size = 0; + dma_region_init(&video->dv_buf); + video->dv_buf_size = 0; + dma_region_init(&video->packet_buf); + video->packet_buf_size = 0; clear_bit(0, &video->open); spin_lock_init(&video->spinlock); @@ -2762,10 +2660,6 @@ list_add_tail(&video->list, &dv1394_cards); spin_unlock_irqrestore(&dv1394_cards_lock, flags); - if (format == DV1394_NTSC) - video->id |= mode; - else video->id |= 2 + mode; - #ifdef CONFIG_DEVFS_FS if (dv1394_devfs_add_entry(video) < 0) goto err_free; |
From: SVN U. <dde...@li...> - 2003-02-01 13:59:47
|
Author: ddennedy Date: 2003-01-07 21:22:18 -0500 (Tue, 07 Jan 2003) New Revision: 739 Modified: trunk/dv1394.c Log: fix oops on mod reload, fix integrity of frame buffer overflow handling Modified: trunk/dv1394.c ============================================================================== --- trunk/dv1394.c (original) +++ trunk/dv1394.c 2003-02-01 08:59:15.000000000 -0500 @@ -909,6 +909,7 @@ u64 chan_mask; int retval = -EINVAL; + debug_printk( "dv1394: initialising %d\n", video->id ); if(init->api_version != DV1394_API_VERSION) goto err; @@ -1177,6 +1178,7 @@ if( (reg_read(video->ohci, video->ohci_IsoXmitContextControlClear) & (1 << 10)) || (reg_read(video->ohci, video->ohci_IsoRcvContextControlClear) & (1 << 10)) ) { /* still active */ + debug_printk("dv1394: stop_dma: DMA not stopped yet\n" ); mb(); } else { debug_printk("dv1394: stop_dma: DMA stopped safely after %d ms\n", i/10); @@ -1190,7 +1192,9 @@ printk(KERN_ERR "dv1394: stop_dma: DMA still going after %d ms!\n", i/10); } } - + else + debug_printk("dv1394: stop_dma: already stopped.\n"); + spin_unlock_irqrestore(&video->spinlock, flags); } @@ -1217,7 +1221,8 @@ /* disable interrupts for IT context */ reg_write(video->ohci, OHCI1394_IsoXmitIntMaskClear, (1 << video->ohci_it_ctx)); - clear_bit(video->ohci_it_ctx, &video->ohci->it_ctx_usage); + /* remove tasklet */ + ohci1394_unregister_iso_tasklet(video->ohci, &video->it_tasklet); debug_printk("dv1394: IT context %d released\n", video->ohci_it_ctx); video->ohci_it_ctx = -1; } @@ -1231,23 +1236,14 @@ /* disable interrupts for IR context */ reg_write(video->ohci, OHCI1394_IsoRecvIntMaskClear, (1 << video->ohci_ir_ctx)); - clear_bit(video->ohci_ir_ctx, &video->ohci->ir_ctx_usage); + /* remove tasklet */ + ohci1394_unregister_iso_tasklet(video->ohci, &video->ir_tasklet); debug_printk("dv1394: IR context %d released\n", video->ohci_ir_ctx); video->ohci_ir_ctx = -1; } spin_unlock_irqrestore(&video->spinlock, flags); - /* remove tasklets */ - if(video->ohci_it_ctx != -1) { - ohci1394_unregister_iso_tasklet(video->ohci, &video->it_tasklet); - video->ohci_it_ctx = -1; - } - if(video->ohci_ir_ctx != -1) { - ohci1394_unregister_iso_tasklet(video->ohci, &video->ir_tasklet); - video->ohci_ir_ctx = -1; - } - /* release the ISO channel */ if(video->channel != -1) { u64 chan_mask; @@ -2337,6 +2333,7 @@ dbc = (int) (p->cip_h1 >> 24); if ( video->continuity_counter != -1 && dbc > ((video->continuity_counter + 1) % 256) ) { + printk(KERN_WARNING "dv1394: discontinuity detected, dropping all frames\n" ); video->dropped_frames += video->n_clear_frames + 1; video->first_frame = 0; video->n_clear_frames = 0; @@ -2355,9 +2352,8 @@ video->n_clear_frames++; if (video->n_clear_frames > video->n_frames) { video->dropped_frames++; - video->n_clear_frames--; - if (video->n_clear_frames < 0) - video->n_clear_frames = 0; + printk(KERN_WARNING "dv1394: dropped a frame during reception\n" ); + video->n_clear_frames = video->n_frames-1; video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames; } if (video->first_clear_frame == -1) @@ -2366,7 +2362,6 @@ /* get the next frame */ video->active_frame = (video->active_frame + 1) % video->n_frames; f = video->frames[video->active_frame]; - irq_printk(" frame received, active_frame = %d, n_clear_frames = %d, first_clear_frame = %d\n", video->active_frame, video->n_clear_frames, video->first_clear_frame); } |
From: SVN U. <ben...@li...> - 2003-02-01 13:59:47
|
Author: bencollins Date: 2003-01-06 07:53:03 -0500 (Mon, 06 Jan 2003) New Revision: 738 Modified: branches/linux-2.4/amdtp.c Log: Null check for kmalloc, patch from Rusty Russell Modified: branches/linux-2.4/amdtp.c ============================================================================== --- branches/linux-2.4/amdtp.c (original) +++ branches/linux-2.4/amdtp.c 2003-02-01 08:59:14.000000000 -0500 @@ -598,6 +598,8 @@ struct buffer *b; b = kmalloc(sizeof *b + size, SLAB_KERNEL); + if (b == NULL) + return NULL; b->head = 0; b->tail = 0; b->length = 0; |
From: SVN U. <ben...@li...> - 2003-02-01 13:59:46
|
Author: bencollins Date: 2003-01-06 07:52:13 -0500 (Mon, 06 Jan 2003) New Revision: 737 Modified: trunk/amdtp.c Log: Null check for kmalloc, patch from Rusty Russell Modified: trunk/amdtp.c ============================================================================== --- trunk/amdtp.c (original) +++ trunk/amdtp.c 2003-02-01 08:59:13.000000000 -0500 @@ -598,6 +598,8 @@ struct buffer *b; b = kmalloc(sizeof *b + size, SLAB_KERNEL); + if (b == NULL) + return NULL; b->head = 0; b->tail = 0; b->length = 0; |
From: SVN U. <dm...@li...> - 2003-02-01 13:59:45
|
Author: dmaas Date: 2003-01-05 23:03:02 -0500 (Sun, 05 Jan 2003) New Revision: 736 Modified: trunk/ohci1394.c trunk/ohci1394.h Log: back out previous commit - don't drop the legacy API just yet Modified: trunk/ohci1394.c ============================================================================== --- trunk/ohci1394.c (original) +++ trunk/ohci1394.c 2003-02-01 08:59:12.000000000 -0500 @@ -515,6 +515,12 @@ /* Don't accept phy packets into AR request context */ reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400); + /* Set bufferFill, isochHeader, multichannel for IR context */ + reg_write(ohci, OHCI1394_IsoRcvContextControlSet, 0xd0000000); + + /* Set the context match register to match on all tags */ + reg_write(ohci, OHCI1394_IsoRcvContextMatch, 0xf0000000); + /* Clear the interrupt mask */ reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff); reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff); @@ -535,6 +541,9 @@ initialize_dma_trm_ctx(&ohci->at_req_context); initialize_dma_trm_ctx(&ohci->at_resp_context); + /* Initialize IR dma */ + initialize_dma_rcv_ctx(&ohci->ir_context, 1); + /* Initialize IT dma */ initialize_dma_trm_ctx(&ohci->it_context); @@ -2739,7 +2748,10 @@ ohci1394_stop_context(d->ohci, d->ctrlClear, NULL); - tasklet_kill(&d->task); + if (d->type == DMA_CTX_ISO) + ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->ir_tasklet); + else + tasklet_kill(&d->task); if (d->buf_cpu) { for (i=0; i<d->num_desc; i++) @@ -2776,12 +2788,6 @@ { int i; - if(type == DMA_CTX_ISO) { - PRINT(KERN_ERR, ohci->id, - "Obsolete ISO reception API removed; use hpsb_iso interface"); - return -EINVAL; - } - d->ohci = ohci; d->type = type; d->ctx = ctx; @@ -2859,7 +2865,18 @@ spin_lock_init(&d->lock); - tasklet_init (&d->task, dma_rcv_tasklet, (unsigned long) d); + if (type == DMA_CTX_ISO) { + ohci1394_init_iso_tasklet(&ohci->ir_tasklet, OHCI_ISO_MULTICHANNEL_RECEIVE, + dma_rcv_tasklet, (unsigned long) d); + if (ohci1394_register_iso_tasklet(ohci, + &ohci->ir_tasklet) < 0) { + PRINT(KERN_ERR, ohci->id, "No IR DMA context available"); + free_dma_rcv_ctx(d); + return -EBUSY; + } + } + else + tasklet_init (&d->task, dma_rcv_tasklet, (unsigned long) d); return 0; } @@ -3309,6 +3326,14 @@ ohci->ISO_channel_usage = 0; spin_lock_init(&ohci->IR_channel_lock); + /* IR DMA context */ + if (alloc_dma_rcv_ctx(ohci, &ohci->ir_context, + DMA_CTX_ISO, 0, IR_NUM_DESC, + IR_BUF_SIZE, IR_SPLIT_BUF_SIZE, + OHCI1394_IsoRcvContextBase) < 0) + FAIL(-ENOMEM, "Failed to allocate IR context"); + + /* IT DMA context allocation */ if (alloc_dma_trm_ctx(ohci, &ohci->it_context, DMA_CTX_ISO, 0, IT_NUM_DESC, @@ -3357,6 +3382,9 @@ free_dma_trm_ctx(&ohci->at_req_context); free_dma_trm_ctx(&ohci->at_resp_context); + /* Free IR dma */ + free_dma_rcv_ctx(&ohci->ir_context); + /* Free IT dma */ free_dma_trm_ctx(&ohci->it_context); Modified: trunk/ohci1394.h ============================================================================== --- trunk/ohci1394.h (original) +++ trunk/ohci1394.h 2003-02-01 08:59:13.000000000 -0500 @@ -188,6 +188,8 @@ struct dma_trm_ctx at_req_context; /* iso receive */ + struct dma_rcv_ctx ir_context; + struct ohci1394_iso_tasklet ir_tasklet; spinlock_t IR_channel_lock; int nb_iso_rcv_ctx; unsigned long ir_ctx_usage; /* use test_and_set_bit() for atomicity */ |
From: SVN U. <dm...@li...> - 2003-02-01 13:59:43
|
Author: dmaas Date: 2003-01-05 16:12:31 -0500 (Sun, 05 Jan 2003) New Revision: 735 Modified: trunk/ohci1394.c trunk/ohci1394.h Log: remove old isochronous reception API (part I) - this frees up the multichannel context for other uses Modified: trunk/ohci1394.c ============================================================================== --- trunk/ohci1394.c (original) +++ trunk/ohci1394.c 2003-02-01 08:59:09.000000000 -0500 @@ -515,12 +515,6 @@ /* Don't accept phy packets into AR request context */ reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400); - /* Set bufferFill, isochHeader, multichannel for IR context */ - reg_write(ohci, OHCI1394_IsoRcvContextControlSet, 0xd0000000); - - /* Set the context match register to match on all tags */ - reg_write(ohci, OHCI1394_IsoRcvContextMatch, 0xf0000000); - /* Clear the interrupt mask */ reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff); reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff); @@ -541,9 +535,6 @@ initialize_dma_trm_ctx(&ohci->at_req_context); initialize_dma_trm_ctx(&ohci->at_resp_context); - /* Initialize IR dma */ - initialize_dma_rcv_ctx(&ohci->ir_context, 1); - /* Initialize IT dma */ initialize_dma_trm_ctx(&ohci->it_context); @@ -2748,10 +2739,7 @@ ohci1394_stop_context(d->ohci, d->ctrlClear, NULL); - if (d->type == DMA_CTX_ISO) - ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->ir_tasklet); - else - tasklet_kill(&d->task); + tasklet_kill(&d->task); if (d->buf_cpu) { for (i=0; i<d->num_desc; i++) @@ -2788,6 +2776,12 @@ { int i; + if(type == DMA_CTX_ISO) { + PRINT(KERN_ERR, ohci->id, + "Obsolete ISO reception API removed; use hpsb_iso interface"); + return -EINVAL; + } + d->ohci = ohci; d->type = type; d->ctx = ctx; @@ -2865,18 +2859,7 @@ spin_lock_init(&d->lock); - if (type == DMA_CTX_ISO) { - ohci1394_init_iso_tasklet(&ohci->ir_tasklet, OHCI_ISO_MULTICHANNEL_RECEIVE, - dma_rcv_tasklet, (unsigned long) d); - if (ohci1394_register_iso_tasklet(ohci, - &ohci->ir_tasklet) < 0) { - PRINT(KERN_ERR, ohci->id, "No IR DMA context available"); - free_dma_rcv_ctx(d); - return -EBUSY; - } - } - else - tasklet_init (&d->task, dma_rcv_tasklet, (unsigned long) d); + tasklet_init (&d->task, dma_rcv_tasklet, (unsigned long) d); return 0; } @@ -3326,14 +3309,6 @@ ohci->ISO_channel_usage = 0; spin_lock_init(&ohci->IR_channel_lock); - /* IR DMA context */ - if (alloc_dma_rcv_ctx(ohci, &ohci->ir_context, - DMA_CTX_ISO, 0, IR_NUM_DESC, - IR_BUF_SIZE, IR_SPLIT_BUF_SIZE, - OHCI1394_IsoRcvContextBase) < 0) - FAIL(-ENOMEM, "Failed to allocate IR context"); - - /* IT DMA context allocation */ if (alloc_dma_trm_ctx(ohci, &ohci->it_context, DMA_CTX_ISO, 0, IT_NUM_DESC, @@ -3382,9 +3357,6 @@ free_dma_trm_ctx(&ohci->at_req_context); free_dma_trm_ctx(&ohci->at_resp_context); - /* Free IR dma */ - free_dma_rcv_ctx(&ohci->ir_context); - /* Free IT dma */ free_dma_trm_ctx(&ohci->it_context); Modified: trunk/ohci1394.h ============================================================================== --- trunk/ohci1394.h (original) +++ trunk/ohci1394.h 2003-02-01 08:59:10.000000000 -0500 @@ -188,8 +188,6 @@ struct dma_trm_ctx at_req_context; /* iso receive */ - struct dma_rcv_ctx ir_context; - struct ohci1394_iso_tasklet ir_tasklet; spinlock_t IR_channel_lock; int nb_iso_rcv_ctx; unsigned long ir_ctx_usage; /* use test_and_set_bit() for atomicity */ |