Commit 8d98c5cd41d1932bb76a3945b4e8dea889224d87

Authored by Jody McIntyre
Committed by Linus Torvalds
1 parent 2554bd2a68

[PATCH] ieee1394: single buffer fixes to video1394

Apply and fixup patch from Markus Tavenrath <speedygoo@speedygoo.de> for
video1394 to allow only a single buffer on receive and two buffers on
transmit.  Tested with libdc1394 and dvconnect (libdv).

Signed-off-by: Dan Dennedy <dan@dennedy.org>
Signed-off-by: Jody McIntyre <scjody@steamballoon.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 1 changed file with 85 additions and 25 deletions Side-by-side Diff

drivers/ieee1394/video1394.c
... ... @@ -35,6 +35,11 @@
35 35 *
36 36 */
37 37  
  38 +/* Markus Tavenrath <speedygoo@speedygoo.de> :
  39 + - fixed checks for valid buffer-numbers in video1394_icotl
  40 + - changed the ways the dma prg's are used, now it's possible to use
  41 + even a single dma buffer
  42 +*/
38 43 #include <linux/config.h>
39 44 #include <linux/kernel.h>
40 45 #include <linux/list.h>
... ... @@ -112,6 +117,7 @@
112 117 struct it_dma_prg **it_prg;
113 118  
114 119 unsigned int *buffer_status;
  120 + unsigned int *buffer_prg_assignment;
115 121 struct timeval *buffer_time; /* time when the buffer was received */
116 122 unsigned int *last_used_cmd; /* For ISO Transmit with
117 123 variable sized packets only ! */
... ... @@ -183,6 +189,7 @@
183 189 kfree(d->ir_prg);
184 190 kfree(d->it_prg);
185 191 kfree(d->buffer_status);
  192 + kfree(d->buffer_prg_assignment);
186 193 kfree(d->buffer_time);
187 194 kfree(d->last_used_cmd);
188 195 kfree(d->next_buffer);
... ... @@ -220,7 +227,7 @@
220 227 /* Init the regions for easy cleanup */
221 228 dma_region_init(&d->dma);
222 229  
223   - if (dma_region_alloc(&d->dma, d->num_desc * d->buf_size, ohci->dev,
  230 + if (dma_region_alloc(&d->dma, (d->num_desc - 1) * d->buf_size, ohci->dev,
224 231 PCI_DMA_BIDIRECTIONAL)) {
225 232 PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma buffer");
226 233 free_dma_iso_ctx(d);
... ... @@ -332,6 +339,8 @@
332 339  
333 340 d->buffer_status = kmalloc(d->num_desc * sizeof(unsigned int),
334 341 GFP_KERNEL);
  342 + d->buffer_prg_assignment = kmalloc(d->num_desc * sizeof(unsigned int),
  343 + GFP_KERNEL);
335 344 d->buffer_time = kmalloc(d->num_desc * sizeof(struct timeval),
336 345 GFP_KERNEL);
337 346 d->last_used_cmd = kmalloc(d->num_desc * sizeof(unsigned int),
... ... @@ -344,6 +353,11 @@
344 353 free_dma_iso_ctx(d);
345 354 return NULL;
346 355 }
  356 + if (d->buffer_prg_assignment == NULL) {
  357 + PRINT(KERN_ERR, ohci->host->id, "Failed to allocate buffer_prg_assignment");
  358 + free_dma_iso_ctx(d);
  359 + return NULL;
  360 + }
347 361 if (d->buffer_time == NULL) {
348 362 PRINT(KERN_ERR, ohci->host->id, "Failed to allocate buffer_time");
349 363 free_dma_iso_ctx(d);
... ... @@ -360,6 +374,7 @@
360 374 return NULL;
361 375 }
362 376 memset(d->buffer_status, 0, d->num_desc * sizeof(unsigned int));
  377 + memset(d->buffer_prg_assignment, 0, d->num_desc * sizeof(unsigned int));
363 378 memset(d->buffer_time, 0, d->num_desc * sizeof(struct timeval));
364 379 memset(d->last_used_cmd, 0, d->num_desc * sizeof(unsigned int));
365 380 memset(d->next_buffer, -1, d->num_desc * sizeof(int));
... ... @@ -369,7 +384,7 @@
369 384 PRINT(KERN_INFO, ohci->host->id, "Iso %s DMA: %d buffers "
370 385 "of size %d allocated for a frame size %d, each with %d prgs",
371 386 (type == OHCI_ISO_RECEIVE) ? "receive" : "transmit",
372   - d->num_desc, d->buf_size, d->frame_size, d->nb_cmd);
  387 + d->num_desc - 1, d->buf_size, d->frame_size, d->nb_cmd);
373 388  
374 389 return d;
375 390 }
376 391  
... ... @@ -384,11 +399,36 @@
384 399 d->ir_prg[n][i].status = cpu_to_le32(d->left_size);
385 400 }
386 401  
  402 +static void reprogram_dma_ir_prg(struct dma_iso_ctx *d, int n, int buffer, int flags)
  403 +{
  404 + struct dma_cmd *ir_prg = d->ir_prg[n];
  405 + unsigned long buf = (unsigned long)d->dma.kvirt + buffer * d->buf_size;
  406 + int i;
  407 +
  408 + d->buffer_prg_assignment[n] = buffer;
  409 +
  410 + ir_prg[0].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, buf -
  411 + (unsigned long)d->dma.kvirt));
  412 + ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
  413 + (buf + 4) - (unsigned long)d->dma.kvirt));
  414 +
  415 + for (i=2;i<d->nb_cmd-1;i++) {
  416 + ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
  417 + (buf+(i-1)*PAGE_SIZE) -
  418 + (unsigned long)d->dma.kvirt));
  419 + }
  420 +
  421 + ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
  422 + DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size);
  423 + ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
  424 + (buf+(i-1)*PAGE_SIZE) - (unsigned long)d->dma.kvirt));
  425 +}
  426 +
387 427 static void initialize_dma_ir_prg(struct dma_iso_ctx *d, int n, int flags)
388 428 {
389 429 struct dma_cmd *ir_prg = d->ir_prg[n];
390 430 struct dma_prog_region *ir_reg = &d->prg_reg[n];
391   - unsigned long buf = (unsigned long)d->dma.kvirt + n * d->buf_size;
  431 + unsigned long buf = (unsigned long)d->dma.kvirt;
392 432 int i;
393 433  
394 434 /* the first descriptor will read only 4 bytes */
... ... @@ -498,7 +538,7 @@
498 538 for (i = 0; i < d->num_desc; i++) {
499 539 if (d->ir_prg[i][d->nb_cmd-1].status & cpu_to_le32(0xFFFF0000)) {
500 540 reset_ir_status(d, i);
501   - d->buffer_status[i] = VIDEO1394_BUFFER_READY;
  541 + d->buffer_status[d->buffer_prg_assignment[i]] = VIDEO1394_BUFFER_READY;
502 542 do_gettimeofday(&d->buffer_time[i]);
503 543 }
504 544 }
... ... @@ -575,7 +615,7 @@
575 615 int next = d->next_buffer[i];
576 616 put_timestamp(ohci, d, next);
577 617 d->it_prg[i][d->last_used_cmd[i]].end.status = 0;
578   - d->buffer_status[i] = VIDEO1394_BUFFER_READY;
  618 + d->buffer_status[d->buffer_prg_assignment[i]] = VIDEO1394_BUFFER_READY;
579 619 }
580 620 }
581 621  
582 622  
... ... @@ -585,11 +625,25 @@
585 625 wake_up_interruptible(&d->waitq);
586 626 }
587 627  
  628 +static void reprogram_dma_it_prg(struct dma_iso_ctx *d, int n, int buffer)
  629 +{
  630 + struct it_dma_prg *it_prg = d->it_prg[n];
  631 + unsigned long buf = (unsigned long)d->dma.kvirt + buffer * d->buf_size;
  632 + int i;
  633 +
  634 + d->buffer_prg_assignment[n] = buffer;
  635 + for (i=0;i<d->nb_cmd;i++) {
  636 + it_prg[i].end.address =
  637 + cpu_to_le32(dma_region_offset_to_bus(&d->dma,
  638 + (buf+i*d->packet_size) - (unsigned long)d->dma.kvirt));
  639 + }
  640 +}
  641 +
588 642 static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag)
589 643 {
590 644 struct it_dma_prg *it_prg = d->it_prg[n];
591 645 struct dma_prog_region *it_reg = &d->prg_reg[n];
592   - unsigned long buf = (unsigned long)d->dma.kvirt + n * d->buf_size;
  646 + unsigned long buf = (unsigned long)d->dma.kvirt;
593 647 int i;
594 648 d->last_used_cmd[n] = d->nb_cmd - 1;
595 649 for (i=0;i<d->nb_cmd;i++) {
... ... @@ -786,7 +840,7 @@
786 840  
787 841 if (cmd == VIDEO1394_IOC_LISTEN_CHANNEL) {
788 842 d = alloc_dma_iso_ctx(ohci, OHCI_ISO_RECEIVE,
789   - v.nb_buffers, v.buf_size,
  843 + v.nb_buffers + 1, v.buf_size,
790 844 v.channel, 0);
791 845  
792 846 if (d == NULL) {
... ... @@ -807,7 +861,7 @@
807 861 }
808 862 else {
809 863 d = alloc_dma_iso_ctx(ohci, OHCI_ISO_TRANSMIT,
810   - v.nb_buffers, v.buf_size,
  864 + v.nb_buffers + 1, v.buf_size,
811 865 v.channel, v.packet_size);
812 866  
813 867 if (d == NULL) {
... ... @@ -879,6 +933,7 @@
879 933 {
880 934 struct video1394_wait v;
881 935 struct dma_iso_ctx *d;
  936 + int next_prg;
882 937  
883 938 if (copy_from_user(&v, argp, sizeof(v)))
884 939 return -EFAULT;
... ... @@ -886,7 +941,7 @@
886 941 d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
887 942 if (d == NULL) return -EFAULT;
888 943  
889   - if ((v.buffer<0) || (v.buffer>d->num_desc)) {
  944 + if ((v.buffer<0) || (v.buffer>=d->num_desc - 1)) {
890 945 PRINT(KERN_ERR, ohci->host->id,
891 946 "Buffer %d out of range",v.buffer);
892 947 return -EINVAL;
893 948  
894 949  
... ... @@ -903,12 +958,14 @@
903 958  
904 959 d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
905 960  
  961 + next_prg = (d->last_buffer + 1) % d->num_desc;
906 962 if (d->last_buffer>=0)
907 963 d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress =
908   - cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0)
  964 + cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg], 0)
909 965 & 0xfffffff0) | 0x1);
910 966  
911   - d->last_buffer = v.buffer;
  967 + d->last_buffer = next_prg;
  968 + reprogram_dma_ir_prg(d, d->last_buffer, v.buffer, d->flags);
912 969  
913 970 d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = 0;
914 971  
... ... @@ -920,7 +977,7 @@
920 977  
921 978 /* Tell the controller where the first program is */
922 979 reg_write(ohci, d->cmdPtr,
923   - dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0) | 0x1);
  980 + dma_prog_region_offset_to_bus(&d->prg_reg[d->last_buffer], 0) | 0x1);
924 981  
925 982 /* Run IR context */
926 983 reg_write(ohci, d->ctrlSet, 0x8000);
... ... @@ -941,7 +998,7 @@
941 998 {
942 999 struct video1394_wait v;
943 1000 struct dma_iso_ctx *d;
944   - int i;
  1001 + int i = 0;
945 1002  
946 1003 if (copy_from_user(&v, argp, sizeof(v)))
947 1004 return -EFAULT;
... ... @@ -949,7 +1006,7 @@
949 1006 d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
950 1007 if (d == NULL) return -EFAULT;
951 1008  
952   - if ((v.buffer<0) || (v.buffer>d->num_desc)) {
  1009 + if ((v.buffer<0) || (v.buffer>d->num_desc - 1)) {
953 1010 PRINT(KERN_ERR, ohci->host->id,
954 1011 "Buffer %d out of range",v.buffer);
955 1012 return -EINVAL;
956 1013  
... ... @@ -995,9 +1052,9 @@
995 1052 * Look ahead to see how many more buffers have been received
996 1053 */
997 1054 i=0;
998   - while (d->buffer_status[(v.buffer+1)%d->num_desc]==
  1055 + while (d->buffer_status[(v.buffer+1)%(d->num_desc - 1)]==
999 1056 VIDEO1394_BUFFER_READY) {
1000   - v.buffer=(v.buffer+1)%d->num_desc;
  1057 + v.buffer=(v.buffer+1)%(d->num_desc - 1);
1001 1058 i++;
1002 1059 }
1003 1060 spin_unlock_irqrestore(&d->lock, flags);
... ... @@ -1013,6 +1070,7 @@
1013 1070 struct video1394_wait v;
1014 1071 unsigned int *psizes = NULL;
1015 1072 struct dma_iso_ctx *d;
  1073 + int next_prg;
1016 1074  
1017 1075 if (copy_from_user(&v, argp, sizeof(v)))
1018 1076 return -EFAULT;
... ... @@ -1020,7 +1078,7 @@
1020 1078 d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
1021 1079 if (d == NULL) return -EFAULT;
1022 1080  
1023   - if ((v.buffer<0) || (v.buffer>d->num_desc)) {
  1081 + if ((v.buffer<0) || (v.buffer>=d->num_desc - 1)) {
1024 1082 PRINT(KERN_ERR, ohci->host->id,
1025 1083 "Buffer %d out of range",v.buffer);
1026 1084 return -EINVAL;
... ... @@ -1046,6 +1104,8 @@
1046 1104  
1047 1105 spin_lock_irqsave(&d->lock,flags);
1048 1106  
  1107 + // last_buffer is last_prg
  1108 + next_prg = (d->last_buffer + 1) % d->num_desc;
1049 1109 if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) {
1050 1110 PRINT(KERN_ERR, ohci->host->id,
1051 1111 "Buffer %d is already used",v.buffer);
... ... @@ -1056,8 +1116,7 @@
1056 1116  
1057 1117 if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) {
1058 1118 initialize_dma_it_prg_var_packet_queue(
1059   - d, v.buffer, psizes,
1060   - ohci);
  1119 + d, next_prg, psizes, ohci);
1061 1120 }
1062 1121  
1063 1122 d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
1064 1123  
1065 1124  
1066 1125  
... ... @@ -1065,16 +1124,17 @@
1065 1124 if (d->last_buffer >= 0) {
1066 1125 d->it_prg[d->last_buffer]
1067 1126 [ d->last_used_cmd[d->last_buffer] ].end.branchAddress =
1068   - cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer],
  1127 + cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg],
1069 1128 0) & 0xfffffff0) | 0x3);
1070 1129  
1071 1130 d->it_prg[d->last_buffer]
1072 1131 [ d->last_used_cmd[d->last_buffer] ].begin.branchAddress =
1073   - cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer],
  1132 + cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg],
1074 1133 0) & 0xfffffff0) | 0x3);
1075   - d->next_buffer[d->last_buffer] = v.buffer;
  1134 + d->next_buffer[d->last_buffer] = (v.buffer + 1) % (d->num_desc - 1);
1076 1135 }
1077   - d->last_buffer = v.buffer;
  1136 + d->last_buffer = next_prg;
  1137 + reprogram_dma_it_prg(d, d->last_buffer, v.buffer);
1078 1138 d->next_buffer[d->last_buffer] = -1;
1079 1139  
1080 1140 d->it_prg[d->last_buffer][d->last_used_cmd[d->last_buffer]].end.branchAddress = 0;
... ... @@ -1089,7 +1149,7 @@
1089 1149  
1090 1150 /* Tell the controller where the first program is */
1091 1151 reg_write(ohci, d->cmdPtr,
1092   - dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0) | 0x3);
  1152 + dma_prog_region_offset_to_bus(&d->prg_reg[next_prg], 0) | 0x3);
1093 1153  
1094 1154 /* Run IT context */
1095 1155 reg_write(ohci, d->ctrlSet, 0x8000);
... ... @@ -1120,7 +1180,7 @@
1120 1180 d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
1121 1181 if (d == NULL) return -EFAULT;
1122 1182  
1123   - if ((v.buffer<0) || (v.buffer>d->num_desc)) {
  1183 + if ((v.buffer<0) || (v.buffer>=d->num_desc-1)) {
1124 1184 PRINT(KERN_ERR, ohci->host->id,
1125 1185 "Buffer %d out of range",v.buffer);
1126 1186 return -EINVAL;