Commit 872e330e38806d835bd6c311c93ab998e2fb9058

Authored by Stefan Richter
1 parent ae2a976614

firewire: add isochronous multichannel reception

This adds the DMA context programming and userspace ABI for multichannel
reception, i.e. for listening on multiple channel numbers by means of a
single DMA context.

The use case is reception of more streams than there are IR DMA units
offered by the link layer.  This is already implemented by the older
ohci1394 + ieee1394 + raw1394 stack.  And as discussed recently on
linux1394-devel, this feature is occasionally used in practice.

The big drawbacks of this mode are that buffer layout and interrupt
generation necessarily differ from single-channel reception:  Headers
and trailers are not stripped from packets, packets are not aligned with
buffer chunks, interrupts are per buffer chunk, not per packet.

These drawbacks also cause a rather hefty code footprint to support this
rarely used OHCI-1394 feature.  (367 lines added, among them 94 lines of
added userspace ABI documentation.)

This implementation enforces that a multichannel reception context may
only listen to channels to which no single-channel context on the same
link layer is presently listening to.  OHCI-1394 would allow to overlay
single-channel contexts by the multi-channel context, but this would be
a departure from the present first-come-first-served policy of IR
context creation.

The implementation is heavily based on an earlier one by Jay Fenlason.
Thanks Jay.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

Showing 6 changed files with 560 additions and 193 deletions Side-by-side Diff

drivers/firewire/core-cdev.c
... ... @@ -193,6 +193,11 @@
193 193 struct fw_cdev_event_iso_interrupt interrupt;
194 194 };
195 195  
  196 +struct iso_interrupt_mc_event {
  197 + struct event event;
  198 + struct fw_cdev_event_iso_interrupt_mc interrupt;
  199 +};
  200 +
196 201 struct iso_resource_event {
197 202 struct event event;
198 203 struct fw_cdev_event_iso_resource iso_resource;
... ... @@ -415,6 +420,7 @@
415 420 struct fw_cdev_get_cycle_timer2 get_cycle_timer2;
416 421 struct fw_cdev_send_phy_packet send_phy_packet;
417 422 struct fw_cdev_receive_phy_packets receive_phy_packets;
  423 + struct fw_cdev_set_iso_channels set_iso_channels;
418 424 };
419 425  
420 426 static int ioctl_get_info(struct client *client, union ioctl_arg *arg)
421 427  
422 428  
423 429  
424 430  
425 431  
426 432  
427 433  
428 434  
429 435  
... ... @@ -932,35 +938,62 @@
932 938 sizeof(e->interrupt) + header_length, NULL, 0);
933 939 }
934 940  
  941 +static void iso_mc_callback(struct fw_iso_context *context,
  942 + dma_addr_t completed, void *data)
  943 +{
  944 + struct client *client = data;
  945 + struct iso_interrupt_mc_event *e;
  946 +
  947 + e = kmalloc(sizeof(*e), GFP_ATOMIC);
  948 + if (e == NULL) {
  949 + fw_notify("Out of memory when allocating event\n");
  950 + return;
  951 + }
  952 + e->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL;
  953 + e->interrupt.closure = client->iso_closure;
  954 + e->interrupt.completed = fw_iso_buffer_lookup(&client->buffer,
  955 + completed);
  956 + queue_event(client, &e->event, &e->interrupt,
  957 + sizeof(e->interrupt), NULL, 0);
  958 +}
  959 +
935 960 static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg)
936 961 {
937 962 struct fw_cdev_create_iso_context *a = &arg->create_iso_context;
938 963 struct fw_iso_context *context;
  964 + fw_iso_callback_t cb;
939 965  
940 966 BUILD_BUG_ON(FW_CDEV_ISO_CONTEXT_TRANSMIT != FW_ISO_CONTEXT_TRANSMIT ||
941   - FW_CDEV_ISO_CONTEXT_RECEIVE != FW_ISO_CONTEXT_RECEIVE);
  967 + FW_CDEV_ISO_CONTEXT_RECEIVE != FW_ISO_CONTEXT_RECEIVE ||
  968 + FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL !=
  969 + FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL);
942 970  
943   - if (a->channel > 63)
944   - return -EINVAL;
945   -
946 971 switch (a->type) {
947   - case FW_ISO_CONTEXT_RECEIVE:
948   - if (a->header_size < 4 || (a->header_size & 3))
  972 + case FW_ISO_CONTEXT_TRANSMIT:
  973 + if (a->speed > SCODE_3200 || a->channel > 63)
949 974 return -EINVAL;
  975 +
  976 + cb = iso_callback;
950 977 break;
951 978  
952   - case FW_ISO_CONTEXT_TRANSMIT:
953   - if (a->speed > SCODE_3200)
  979 + case FW_ISO_CONTEXT_RECEIVE:
  980 + if (a->header_size < 4 || (a->header_size & 3) ||
  981 + a->channel > 63)
954 982 return -EINVAL;
  983 +
  984 + cb = iso_callback;
955 985 break;
956 986  
  987 + case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
  988 + cb = (fw_iso_callback_t)iso_mc_callback;
  989 + break;
  990 +
957 991 default:
958 992 return -EINVAL;
959 993 }
960 994  
961 995 context = fw_iso_context_create(client->device->card, a->type,
962   - a->channel, a->speed, a->header_size,
963   - iso_callback, client);
  996 + a->channel, a->speed, a->header_size, cb, client);
964 997 if (IS_ERR(context))
965 998 return PTR_ERR(context);
966 999  
... ... @@ -980,6 +1013,17 @@
980 1013 return 0;
981 1014 }
982 1015  
  1016 +static int ioctl_set_iso_channels(struct client *client, union ioctl_arg *arg)
  1017 +{
  1018 + struct fw_cdev_set_iso_channels *a = &arg->set_iso_channels;
  1019 + struct fw_iso_context *ctx = client->iso_context;
  1020 +
  1021 + if (ctx == NULL || a->handle != 0)
  1022 + return -EINVAL;
  1023 +
  1024 + return fw_iso_context_set_channels(ctx, &a->channels);
  1025 +}
  1026 +
983 1027 /* Macros for decoding the iso packet control header. */
984 1028 #define GET_PAYLOAD_LENGTH(v) ((v) & 0xffff)
985 1029 #define GET_INTERRUPT(v) (((v) >> 16) & 0x01)
... ... @@ -993,7 +1037,7 @@
993 1037 struct fw_cdev_queue_iso *a = &arg->queue_iso;
994 1038 struct fw_cdev_iso_packet __user *p, *end, *next;
995 1039 struct fw_iso_context *ctx = client->iso_context;
996   - unsigned long payload, buffer_end, transmit_header_bytes;
  1040 + unsigned long payload, buffer_end, transmit_header_bytes = 0;
997 1041 u32 control;
998 1042 int count;
999 1043 struct {
... ... @@ -1013,7 +1057,6 @@
1013 1057 * use the indirect payload, the iso buffer need not be mapped
1014 1058 * and the a->data pointer is ignored.
1015 1059 */
1016   -
1017 1060 payload = (unsigned long)a->data - client->vm_start;
1018 1061 buffer_end = client->buffer.page_count << PAGE_SHIFT;
1019 1062 if (a->data == 0 || client->buffer.pages == NULL ||
1020 1063  
... ... @@ -1022,8 +1065,10 @@
1022 1065 buffer_end = 0;
1023 1066 }
1024 1067  
1025   - p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(a->packets);
  1068 + if (ctx->type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL && payload & 3)
  1069 + return -EINVAL;
1026 1070  
  1071 + p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(a->packets);
1027 1072 if (!access_ok(VERIFY_READ, p, a->size))
1028 1073 return -EFAULT;
1029 1074  
1030 1075  
1031 1076  
... ... @@ -1039,19 +1084,24 @@
1039 1084 u.packet.sy = GET_SY(control);
1040 1085 u.packet.header_length = GET_HEADER_LENGTH(control);
1041 1086  
1042   - if (ctx->type == FW_ISO_CONTEXT_TRANSMIT) {
1043   - if (u.packet.header_length % 4 != 0)
  1087 + switch (ctx->type) {
  1088 + case FW_ISO_CONTEXT_TRANSMIT:
  1089 + if (u.packet.header_length & 3)
1044 1090 return -EINVAL;
1045 1091 transmit_header_bytes = u.packet.header_length;
1046   - } else {
1047   - /*
1048   - * We require that header_length is a multiple of
1049   - * the fixed header size, ctx->header_size.
1050   - */
  1092 + break;
  1093 +
  1094 + case FW_ISO_CONTEXT_RECEIVE:
1051 1095 if (u.packet.header_length == 0 ||
1052 1096 u.packet.header_length % ctx->header_size != 0)
1053 1097 return -EINVAL;
1054   - transmit_header_bytes = 0;
  1098 + break;
  1099 +
  1100 + case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
  1101 + if (u.packet.payload_length == 0 ||
  1102 + u.packet.payload_length & 3)
  1103 + return -EINVAL;
  1104 + break;
1055 1105 }
1056 1106  
1057 1107 next = (struct fw_cdev_iso_packet __user *)
... ... @@ -1534,6 +1584,7 @@
1534 1584 [0x14] = ioctl_get_cycle_timer2,
1535 1585 [0x15] = ioctl_send_phy_packet,
1536 1586 [0x16] = ioctl_receive_phy_packets,
  1587 + [0x17] = ioctl_set_iso_channels,
1537 1588 };
1538 1589  
1539 1590 static int dispatch_ioctl(struct client *client,
drivers/firewire/core-iso.c
... ... @@ -117,6 +117,23 @@
117 117 }
118 118 EXPORT_SYMBOL(fw_iso_buffer_destroy);
119 119  
  120 +/* Convert DMA address to offset into virtually contiguous buffer. */
  121 +size_t fw_iso_buffer_lookup(struct fw_iso_buffer *buffer, dma_addr_t completed)
  122 +{
  123 + int i;
  124 + dma_addr_t address;
  125 + ssize_t offset;
  126 +
  127 + for (i = 0; i < buffer->page_count; i++) {
  128 + address = page_private(buffer->pages[i]);
  129 + offset = (ssize_t)completed - (ssize_t)address;
  130 + if (offset > 0 && offset <= PAGE_SIZE)
  131 + return (i << PAGE_SHIFT) + offset;
  132 + }
  133 +
  134 + return 0;
  135 +}
  136 +
120 137 struct fw_iso_context *fw_iso_context_create(struct fw_card *card,
121 138 int type, int channel, int speed, size_t header_size,
122 139 fw_iso_callback_t callback, void *callback_data)
... ... @@ -133,7 +150,7 @@
133 150 ctx->channel = channel;
134 151 ctx->speed = speed;
135 152 ctx->header_size = header_size;
136   - ctx->callback = callback;
  153 + ctx->callback.sc = callback;
137 154 ctx->callback_data = callback_data;
138 155  
139 156 return ctx;
... ... @@ -142,9 +159,7 @@
142 159  
143 160 void fw_iso_context_destroy(struct fw_iso_context *ctx)
144 161 {
145   - struct fw_card *card = ctx->card;
146   -
147   - card->driver->free_iso_context(ctx);
  162 + ctx->card->driver->free_iso_context(ctx);
148 163 }
149 164 EXPORT_SYMBOL(fw_iso_context_destroy);
150 165  
151 166  
... ... @@ -155,14 +170,17 @@
155 170 }
156 171 EXPORT_SYMBOL(fw_iso_context_start);
157 172  
  173 +int fw_iso_context_set_channels(struct fw_iso_context *ctx, u64 *channels)
  174 +{
  175 + return ctx->card->driver->set_iso_channels(ctx, channels);
  176 +}
  177 +
158 178 int fw_iso_context_queue(struct fw_iso_context *ctx,
159 179 struct fw_iso_packet *packet,
160 180 struct fw_iso_buffer *buffer,
161 181 unsigned long payload)
162 182 {
163   - struct fw_card *card = ctx->card;
164   -
165   - return card->driver->queue_iso(ctx, packet, buffer, payload);
  183 + return ctx->card->driver->queue_iso(ctx, packet, buffer, payload);
166 184 }
167 185 EXPORT_SYMBOL(fw_iso_context_queue);
168 186  
drivers/firewire/core.h
... ... @@ -90,6 +90,8 @@
90 90 int (*start_iso)(struct fw_iso_context *ctx,
91 91 s32 cycle, u32 sync, u32 tags);
92 92  
  93 + int (*set_iso_channels)(struct fw_iso_context *ctx, u64 *channels);
  94 +
93 95 int (*queue_iso)(struct fw_iso_context *ctx,
94 96 struct fw_iso_packet *packet,
95 97 struct fw_iso_buffer *buffer,
drivers/firewire/ohci.c
... ... @@ -190,11 +190,13 @@
190 190 struct context at_request_ctx;
191 191 struct context at_response_ctx;
192 192  
193   - u32 it_context_mask;
  193 + u32 it_context_mask; /* unoccupied IT contexts */
194 194 struct iso_context *it_context_list;
195   - u64 ir_context_channels;
196   - u32 ir_context_mask;
  195 + u64 ir_context_channels; /* unoccupied channels */
  196 + u32 ir_context_mask; /* unoccupied IR contexts */
197 197 struct iso_context *ir_context_list;
  198 + u64 mc_channels; /* channels in use by the multichannel IR context */
  199 + bool mc_allocated;
198 200  
199 201 __be32 *config_rom;
200 202 dma_addr_t config_rom_bus;
201 203  
... ... @@ -2197,10 +2199,9 @@
2197 2199 __le32 *ir_header;
2198 2200 void *p;
2199 2201  
2200   - for (pd = d; pd <= last; pd++) {
  2202 + for (pd = d; pd <= last; pd++)
2201 2203 if (pd->transfer_status)
2202 2204 break;
2203   - }
2204 2205 if (pd > last)
2205 2206 /* Descriptor(s) not done yet, stop iteration */
2206 2207 return 0;
2207 2208  
... ... @@ -2210,16 +2211,38 @@
2210 2211  
2211 2212 if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) {
2212 2213 ir_header = (__le32 *) p;
2213   - ctx->base.callback(&ctx->base,
2214   - le32_to_cpu(ir_header[0]) & 0xffff,
2215   - ctx->header_length, ctx->header,
2216   - ctx->base.callback_data);
  2214 + ctx->base.callback.sc(&ctx->base,
  2215 + le32_to_cpu(ir_header[0]) & 0xffff,
  2216 + ctx->header_length, ctx->header,
  2217 + ctx->base.callback_data);
2217 2218 ctx->header_length = 0;
2218 2219 }
2219 2220  
2220 2221 return 1;
2221 2222 }
2222 2223  
  2224 +/* d == last because each descriptor block is only a single descriptor. */
  2225 +static int handle_ir_buffer_fill(struct context *context,
  2226 + struct descriptor *d,
  2227 + struct descriptor *last)
  2228 +{
  2229 + struct iso_context *ctx =
  2230 + container_of(context, struct iso_context, context);
  2231 +
  2232 + if (!last->transfer_status)
  2233 + /* Descriptor(s) not done yet, stop iteration */
  2234 + return 0;
  2235 +
  2236 + if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS)
  2237 + ctx->base.callback.mc(&ctx->base,
  2238 + le32_to_cpu(last->data_address) +
  2239 + le16_to_cpu(last->req_count) -
  2240 + le16_to_cpu(last->res_count),
  2241 + ctx->base.callback_data);
  2242 +
  2243 + return 1;
  2244 +}
  2245 +
2223 2246 static int handle_it_packet(struct context *context,
2224 2247 struct descriptor *d,
2225 2248 struct descriptor *last)
2226 2249  
2227 2250  
2228 2251  
2229 2252  
2230 2253  
2231 2254  
2232 2255  
2233 2256  
2234 2257  
2235 2258  
2236 2259  
2237 2260  
2238 2261  
2239 2262  
2240 2263  
2241 2264  
... ... @@ -2245,72 +2268,118 @@
2245 2268 ctx->header_length += 4;
2246 2269 }
2247 2270 if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) {
2248   - ctx->base.callback(&ctx->base, le16_to_cpu(last->res_count),
2249   - ctx->header_length, ctx->header,
2250   - ctx->base.callback_data);
  2271 + ctx->base.callback.sc(&ctx->base, le16_to_cpu(last->res_count),
  2272 + ctx->header_length, ctx->header,
  2273 + ctx->base.callback_data);
2251 2274 ctx->header_length = 0;
2252 2275 }
2253 2276 return 1;
2254 2277 }
2255 2278  
  2279 +static void set_multichannel_mask(struct fw_ohci *ohci, u64 channels)
  2280 +{
  2281 + u32 hi = channels >> 32, lo = channels;
  2282 +
  2283 + reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, ~hi);
  2284 + reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, ~lo);
  2285 + reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet, hi);
  2286 + reg_write(ohci, OHCI1394_IRMultiChanMaskLoSet, lo);
  2287 + mmiowb();
  2288 + ohci->mc_channels = channels;
  2289 +}
  2290 +
2256 2291 static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
2257 2292 int type, int channel, size_t header_size)
2258 2293 {
2259 2294 struct fw_ohci *ohci = fw_ohci(card);
2260   - struct iso_context *ctx, *list;
2261   - descriptor_callback_t callback;
2262   - u64 *channels, dont_care = ~0ULL;
2263   - u32 *mask, regs;
  2295 + struct iso_context *uninitialized_var(ctx);
  2296 + descriptor_callback_t uninitialized_var(callback);
  2297 + u64 *uninitialized_var(channels);
  2298 + u32 *uninitialized_var(mask), uninitialized_var(regs);
2264 2299 unsigned long flags;
2265   - int index, ret = -ENOMEM;
  2300 + int index, ret = -EBUSY;
2266 2301  
2267   - if (type == FW_ISO_CONTEXT_TRANSMIT) {
2268   - channels = &dont_care;
2269   - mask = &ohci->it_context_mask;
2270   - list = ohci->it_context_list;
  2302 + spin_lock_irqsave(&ohci->lock, flags);
  2303 +
  2304 + switch (type) {
  2305 + case FW_ISO_CONTEXT_TRANSMIT:
  2306 + mask = &ohci->it_context_mask;
2271 2307 callback = handle_it_packet;
2272   - } else {
  2308 + index = ffs(*mask) - 1;
  2309 + if (index >= 0) {
  2310 + *mask &= ~(1 << index);
  2311 + regs = OHCI1394_IsoXmitContextBase(index);
  2312 + ctx = &ohci->it_context_list[index];
  2313 + }
  2314 + break;
  2315 +
  2316 + case FW_ISO_CONTEXT_RECEIVE:
2273 2317 channels = &ohci->ir_context_channels;
2274   - mask = &ohci->ir_context_mask;
2275   - list = ohci->ir_context_list;
  2318 + mask = &ohci->ir_context_mask;
2276 2319 callback = handle_ir_packet_per_buffer;
2277   - }
  2320 + index = *channels & 1ULL << channel ? ffs(*mask) - 1 : -1;
  2321 + if (index >= 0) {
  2322 + *channels &= ~(1ULL << channel);
  2323 + *mask &= ~(1 << index);
  2324 + regs = OHCI1394_IsoRcvContextBase(index);
  2325 + ctx = &ohci->ir_context_list[index];
  2326 + }
  2327 + break;
2278 2328  
2279   - spin_lock_irqsave(&ohci->lock, flags);
2280   - index = *channels & 1ULL << channel ? ffs(*mask) - 1 : -1;
2281   - if (index >= 0) {
2282   - *channels &= ~(1ULL << channel);
2283   - *mask &= ~(1 << index);
  2329 + case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
  2330 + mask = &ohci->ir_context_mask;
  2331 + callback = handle_ir_buffer_fill;
  2332 + index = !ohci->mc_allocated ? ffs(*mask) - 1 : -1;
  2333 + if (index >= 0) {
  2334 + ohci->mc_allocated = true;
  2335 + *mask &= ~(1 << index);
  2336 + regs = OHCI1394_IsoRcvContextBase(index);
  2337 + ctx = &ohci->ir_context_list[index];
  2338 + }
  2339 + break;
  2340 +
  2341 + default:
  2342 + index = -1;
  2343 + ret = -ENOSYS;
2284 2344 }
  2345 +
2285 2346 spin_unlock_irqrestore(&ohci->lock, flags);
2286 2347  
2287 2348 if (index < 0)
2288   - return ERR_PTR(-EBUSY);
  2349 + return ERR_PTR(ret);
2289 2350  
2290   - if (type == FW_ISO_CONTEXT_TRANSMIT)
2291   - regs = OHCI1394_IsoXmitContextBase(index);
2292   - else
2293   - regs = OHCI1394_IsoRcvContextBase(index);
2294   -
2295   - ctx = &list[index];
2296 2351 memset(ctx, 0, sizeof(*ctx));
2297 2352 ctx->header_length = 0;
2298 2353 ctx->header = (void *) __get_free_page(GFP_KERNEL);
2299   - if (ctx->header == NULL)
  2354 + if (ctx->header == NULL) {
  2355 + ret = -ENOMEM;
2300 2356 goto out;
2301   -
  2357 + }
2302 2358 ret = context_init(&ctx->context, ohci, regs, callback);
2303 2359 if (ret < 0)
2304 2360 goto out_with_header;
2305 2361  
  2362 + if (type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL)
  2363 + set_multichannel_mask(ohci, 0);
  2364 +
2306 2365 return &ctx->base;
2307 2366  
2308 2367 out_with_header:
2309 2368 free_page((unsigned long)ctx->header);
2310 2369 out:
2311 2370 spin_lock_irqsave(&ohci->lock, flags);
2312   - *channels |= 1ULL << channel;
  2371 +
  2372 + switch (type) {
  2373 + case FW_ISO_CONTEXT_RECEIVE:
  2374 + *channels |= 1ULL << channel;
  2375 + break;
  2376 +
  2377 + case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
  2378 + ohci->mc_allocated = false;
  2379 + break;
  2380 + }
2313 2381 *mask |= 1 << index;
  2382 +
2314 2383 spin_unlock_irqrestore(&ohci->lock, flags);
2315 2384  
2316 2385 return ERR_PTR(ret);
2317 2386  
... ... @@ -2321,10 +2390,11 @@
2321 2390 {
2322 2391 struct iso_context *ctx = container_of(base, struct iso_context, base);
2323 2392 struct fw_ohci *ohci = ctx->context.ohci;
2324   - u32 control, match;
  2393 + u32 control = IR_CONTEXT_ISOCH_HEADER, match;
2325 2394 int index;
2326 2395  
2327   - if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) {
  2396 + switch (ctx->base.type) {
  2397 + case FW_ISO_CONTEXT_TRANSMIT:
2328 2398 index = ctx - ohci->it_context_list;
2329 2399 match = 0;
2330 2400 if (cycle >= 0)
2331 2401  
... ... @@ -2334,9 +2404,13 @@
2334 2404 reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 1 << index);
2335 2405 reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << index);
2336 2406 context_run(&ctx->context, match);
2337   - } else {
  2407 + break;
  2408 +
  2409 + case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
  2410 + control |= IR_CONTEXT_BUFFER_FILL|IR_CONTEXT_MULTI_CHANNEL_MODE;
  2411 + /* fall through */
  2412 + case FW_ISO_CONTEXT_RECEIVE:
2338 2413 index = ctx - ohci->ir_context_list;
2339   - control = IR_CONTEXT_ISOCH_HEADER;
2340 2414 match = (tags << 28) | (sync << 8) | ctx->base.channel;
2341 2415 if (cycle >= 0) {
2342 2416 match |= (cycle & 0x07fff) << 12;
... ... @@ -2347,6 +2421,7 @@
2347 2421 reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index);
2348 2422 reg_write(ohci, CONTEXT_MATCH(ctx->context.regs), match);
2349 2423 context_run(&ctx->context, control);
  2424 + break;
2350 2425 }
2351 2426  
2352 2427 return 0;
2353 2428  
2354 2429  
... ... @@ -2358,12 +2433,17 @@
2358 2433 struct iso_context *ctx = container_of(base, struct iso_context, base);
2359 2434 int index;
2360 2435  
2361   - if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) {
  2436 + switch (ctx->base.type) {
  2437 + case FW_ISO_CONTEXT_TRANSMIT:
2362 2438 index = ctx - ohci->it_context_list;
2363 2439 reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 1 << index);
2364   - } else {
  2440 + break;
  2441 +
  2442 + case FW_ISO_CONTEXT_RECEIVE:
  2443 + case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
2365 2444 index = ctx - ohci->ir_context_list;
2366 2445 reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 1 << index);
  2446 + break;
2367 2447 }
2368 2448 flush_writes(ohci);
2369 2449 context_stop(&ctx->context);
2370 2450  
2371 2451  
2372 2452  
2373 2453  
... ... @@ -2384,24 +2464,65 @@
2384 2464  
2385 2465 spin_lock_irqsave(&ohci->lock, flags);
2386 2466  
2387   - if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) {
  2467 + switch (base->type) {
  2468 + case FW_ISO_CONTEXT_TRANSMIT:
2388 2469 index = ctx - ohci->it_context_list;
2389 2470 ohci->it_context_mask |= 1 << index;
2390   - } else {
  2471 + break;
  2472 +
  2473 + case FW_ISO_CONTEXT_RECEIVE:
2391 2474 index = ctx - ohci->ir_context_list;
2392 2475 ohci->ir_context_mask |= 1 << index;
2393 2476 ohci->ir_context_channels |= 1ULL << base->channel;
  2477 + break;
  2478 +
  2479 + case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
  2480 + index = ctx - ohci->ir_context_list;
  2481 + ohci->ir_context_mask |= 1 << index;
  2482 + ohci->ir_context_channels |= ohci->mc_channels;
  2483 + ohci->mc_channels = 0;
  2484 + ohci->mc_allocated = false;
  2485 + break;
2394 2486 }
2395 2487  
2396 2488 spin_unlock_irqrestore(&ohci->lock, flags);
2397 2489 }
2398 2490  
2399   -static int ohci_queue_iso_transmit(struct fw_iso_context *base,
2400   - struct fw_iso_packet *packet,
2401   - struct fw_iso_buffer *buffer,
2402   - unsigned long payload)
  2491 +static int ohci_set_iso_channels(struct fw_iso_context *base, u64 *channels)
2403 2492 {
2404   - struct iso_context *ctx = container_of(base, struct iso_context, base);
  2493 + struct fw_ohci *ohci = fw_ohci(base->card);
  2494 + unsigned long flags;
  2495 + int ret;
  2496 +
  2497 + switch (base->type) {
  2498 + case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
  2499 +
  2500 + spin_lock_irqsave(&ohci->lock, flags);
  2501 +
  2502 + /* Don't allow multichannel to grab other contexts' channels. */
  2503 + if (~ohci->ir_context_channels & ~ohci->mc_channels & *channels) {
  2504 + *channels = ohci->ir_context_channels;
  2505 + ret = -EBUSY;
  2506 + } else {
  2507 + set_multichannel_mask(ohci, *channels);
  2508 + ret = 0;
  2509 + }
  2510 +
  2511 + spin_unlock_irqrestore(&ohci->lock, flags);
  2512 +
  2513 + break;
  2514 + default:
  2515 + ret = -EINVAL;
  2516 + }
  2517 +
  2518 + return ret;
  2519 +}
  2520 +
  2521 +static int queue_iso_transmit(struct iso_context *ctx,
  2522 + struct fw_iso_packet *packet,
  2523 + struct fw_iso_buffer *buffer,
  2524 + unsigned long payload)
  2525 +{
2405 2526 struct descriptor *d, *last, *pd;
2406 2527 struct fw_iso_packet *p;
2407 2528 __le32 *header;
2408 2529  
2409 2530  
... ... @@ -2497,14 +2618,12 @@
2497 2618 return 0;
2498 2619 }
2499 2620  
2500   -static int ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base,
2501   - struct fw_iso_packet *packet,
2502   - struct fw_iso_buffer *buffer,
2503   - unsigned long payload)
  2621 +static int queue_iso_packet_per_buffer(struct iso_context *ctx,
  2622 + struct fw_iso_packet *packet,
  2623 + struct fw_iso_buffer *buffer,
  2624 + unsigned long payload)
2504 2625 {
2505   - struct iso_context *ctx = container_of(base, struct iso_context, base);
2506 2626 struct descriptor *d, *pd;
2507   - struct fw_iso_packet *p = packet;
2508 2627 dma_addr_t d_bus, page_bus;
2509 2628 u32 z, header_z, rest;
2510 2629 int i, j, length;
2511 2630  
... ... @@ -2514,14 +2633,14 @@
2514 2633 * The OHCI controller puts the isochronous header and trailer in the
2515 2634 * buffer, so we need at least 8 bytes.
2516 2635 */
2517   - packet_count = p->header_length / ctx->base.header_size;
  2636 + packet_count = packet->header_length / ctx->base.header_size;
2518 2637 header_size = max(ctx->base.header_size, (size_t)8);
2519 2638  
2520 2639 /* Get header size in number of descriptors. */
2521 2640 header_z = DIV_ROUND_UP(header_size, sizeof(*d));
2522 2641 page = payload >> PAGE_SHIFT;
2523 2642 offset = payload & ~PAGE_MASK;
2524   - payload_per_buffer = p->payload_length / packet_count;
  2643 + payload_per_buffer = packet->payload_length / packet_count;
2525 2644  
2526 2645 for (i = 0; i < packet_count; i++) {
2527 2646 /* d points to the header descriptor */
... ... @@ -2533,7 +2652,7 @@
2533 2652  
2534 2653 d->control = cpu_to_le16(DESCRIPTOR_STATUS |
2535 2654 DESCRIPTOR_INPUT_MORE);
2536   - if (p->skip && i == 0)
  2655 + if (packet->skip && i == 0)
2537 2656 d->control |= cpu_to_le16(DESCRIPTOR_WAIT);
2538 2657 d->req_count = cpu_to_le16(header_size);
2539 2658 d->res_count = d->req_count;
... ... @@ -2566,7 +2685,7 @@
2566 2685 pd->control = cpu_to_le16(DESCRIPTOR_STATUS |
2567 2686 DESCRIPTOR_INPUT_LAST |
2568 2687 DESCRIPTOR_BRANCH_ALWAYS);
2569   - if (p->interrupt && i == packet_count - 1)
  2688 + if (packet->interrupt && i == packet_count - 1)
2570 2689 pd->control |= cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS);
2571 2690  
2572 2691 context_append(&ctx->context, d, z, header_z);
... ... @@ -2575,6 +2694,58 @@
2575 2694 return 0;
2576 2695 }
2577 2696  
  2697 +static int queue_iso_buffer_fill(struct iso_context *ctx,
  2698 + struct fw_iso_packet *packet,
  2699 + struct fw_iso_buffer *buffer,
  2700 + unsigned long payload)
  2701 +{
  2702 + struct descriptor *d;
  2703 + dma_addr_t d_bus, page_bus;
  2704 + int page, offset, rest, z, i, length;
  2705 +
  2706 + page = payload >> PAGE_SHIFT;
  2707 + offset = payload & ~PAGE_MASK;
  2708 + rest = packet->payload_length;
  2709 +
  2710 + /* We need one descriptor for each page in the buffer. */
  2711 + z = DIV_ROUND_UP(offset + rest, PAGE_SIZE);
  2712 +
  2713 + if (WARN_ON(offset & 3 || rest & 3 || page + z > buffer->page_count))
  2714 + return -EFAULT;
  2715 +
  2716 + for (i = 0; i < z; i++) {
  2717 + d = context_get_descriptors(&ctx->context, 1, &d_bus);
  2718 + if (d == NULL)
  2719 + return -ENOMEM;
  2720 +
  2721 + d->control = cpu_to_le16(DESCRIPTOR_INPUT_MORE |
  2722 + DESCRIPTOR_BRANCH_ALWAYS);
  2723 + if (packet->skip && i == 0)
  2724 + d->control |= cpu_to_le16(DESCRIPTOR_WAIT);
  2725 + if (packet->interrupt && i == z - 1)
  2726 + d->control |= cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS);
  2727 +
  2728 + if (offset + rest < PAGE_SIZE)
  2729 + length = rest;
  2730 + else
  2731 + length = PAGE_SIZE - offset;
  2732 + d->req_count = cpu_to_le16(length);
  2733 + d->res_count = d->req_count;
  2734 + d->transfer_status = 0;
  2735 +
  2736 + page_bus = page_private(buffer->pages[page]);
  2737 + d->data_address = cpu_to_le32(page_bus + offset);
  2738 +
  2739 + rest -= length;
  2740 + offset = 0;
  2741 + page++;
  2742 +
  2743 + context_append(&ctx->context, d, 1, 0);
  2744 + }
  2745 +
  2746 + return 0;
  2747 +}
  2748 +
2578 2749 static int ohci_queue_iso(struct fw_iso_context *base,
2579 2750 struct fw_iso_packet *packet,
2580 2751 struct fw_iso_buffer *buffer,
2581 2752  
... ... @@ -2582,14 +2753,20 @@
2582 2753 {
2583 2754 struct iso_context *ctx = container_of(base, struct iso_context, base);
2584 2755 unsigned long flags;
2585   - int ret;
  2756 + int ret = -ENOSYS;
2586 2757  
2587 2758 spin_lock_irqsave(&ctx->context.ohci->lock, flags);
2588   - if (base->type == FW_ISO_CONTEXT_TRANSMIT)
2589   - ret = ohci_queue_iso_transmit(base, packet, buffer, payload);
2590   - else
2591   - ret = ohci_queue_iso_receive_packet_per_buffer(base, packet,
2592   - buffer, payload);
  2759 + switch (base->type) {
  2760 + case FW_ISO_CONTEXT_TRANSMIT:
  2761 + ret = queue_iso_transmit(ctx, packet, buffer, payload);
  2762 + break;
  2763 + case FW_ISO_CONTEXT_RECEIVE:
  2764 + ret = queue_iso_packet_per_buffer(ctx, packet, buffer, payload);
  2765 + break;
  2766 + case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
  2767 + ret = queue_iso_buffer_fill(ctx, packet, buffer, payload);
  2768 + break;
  2769 + }
2593 2770 spin_unlock_irqrestore(&ctx->context.ohci->lock, flags);
2594 2771  
2595 2772 return ret;
... ... @@ -2609,6 +2786,7 @@
2609 2786  
2610 2787 .allocate_iso_context = ohci_allocate_iso_context,
2611 2788 .free_iso_context = ohci_free_iso_context,
  2789 + .set_iso_channels = ohci_set_iso_channels,
2612 2790 .queue_iso = ohci_queue_iso,
2613 2791 .start_iso = ohci_start_iso,
2614 2792 .stop_iso = ohci_stop_iso,
include/linux/firewire-cdev.h
... ... @@ -25,17 +25,18 @@
25 25 #include <linux/types.h>
26 26 #include <linux/firewire-constants.h>
27 27  
28   -#define FW_CDEV_EVENT_BUS_RESET 0x00
29   -#define FW_CDEV_EVENT_RESPONSE 0x01
30   -#define FW_CDEV_EVENT_REQUEST 0x02
31   -#define FW_CDEV_EVENT_ISO_INTERRUPT 0x03
32   -#define FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED 0x04
33   -#define FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED 0x05
  28 +#define FW_CDEV_EVENT_BUS_RESET 0x00
  29 +#define FW_CDEV_EVENT_RESPONSE 0x01
  30 +#define FW_CDEV_EVENT_REQUEST 0x02
  31 +#define FW_CDEV_EVENT_ISO_INTERRUPT 0x03
  32 +#define FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED 0x04
  33 +#define FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED 0x05
34 34  
35 35 /* available since kernel version 2.6.36 */
36   -#define FW_CDEV_EVENT_REQUEST2 0x06
37   -#define FW_CDEV_EVENT_PHY_PACKET_SENT 0x07
38   -#define FW_CDEV_EVENT_PHY_PACKET_RECEIVED 0x08
  36 +#define FW_CDEV_EVENT_REQUEST2 0x06
  37 +#define FW_CDEV_EVENT_PHY_PACKET_SENT 0x07
  38 +#define FW_CDEV_EVENT_PHY_PACKET_RECEIVED 0x08
  39 +#define FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL 0x09
39 40  
40 41 /**
41 42 * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types
42 43  
43 44  
44 45  
45 46  
46 47  
47 48  
... ... @@ -218,35 +219,41 @@
218 219 * This event is sent when the controller has completed an &fw_cdev_iso_packet
219 220 * with the %FW_CDEV_ISO_INTERRUPT bit set.
220 221 *
221   - * Isochronous transmit events:
  222 + * Isochronous transmit events (context type %FW_CDEV_ISO_CONTEXT_TRANSMIT):
222 223 *
223   - * In version 1 of the ABI, &header_length is 0. In version 3 and some
224   - * implementations of version 2 of the ABI, &header_length is a multiple of 4
225   - * and &header contains timestamps of all packets up until the interrupt packet.
226   - * The format of the timestamps is as described below for isochronous reception.
  224 + * In version 3 and some implementations of version 2 of the ABI, &header_length
  225 + * is a multiple of 4 and &header contains timestamps of all packets up until
  226 + * the interrupt packet. The format of the timestamps is as described below for
  227 + * isochronous reception. In version 1 of the ABI, &header_length was 0.
227 228 *
228   - * Isochronous receive events:
  229 + * Isochronous receive events (context type %FW_CDEV_ISO_CONTEXT_RECEIVE):
229 230 *
230 231 * The headers stripped of all packets up until and including the interrupt
231 232 * packet are returned in the @header field. The amount of header data per
232 233 * packet is as specified at iso context creation by
233 234 * &fw_cdev_create_iso_context.header_size.
234 235 *
235   - * In version 1 of this ABI, header data consisted of the 1394 isochronous
236   - * packet header, followed by quadlets from the packet payload if
237   - * &fw_cdev_create_iso_context.header_size > 4.
  236 + * Hence, _interrupt.header_length / _context.header_size is the number of
  237 + * packets received in this interrupt event. The client can now iterate
  238 + * through the mmap()'ed DMA buffer according to this number of packets and
  239 + * to the buffer sizes as the client specified in &fw_cdev_queue_iso.
238 240 *
239   - * In version 2 of this ABI, header data consist of the 1394 isochronous
240   - * packet header, followed by a timestamp quadlet if
241   - * &fw_cdev_create_iso_context.header_size > 4, followed by quadlets from the
242   - * packet payload if &fw_cdev_create_iso_context.header_size > 8.
  241 + * Since version 2 of this ABI, the portion for each packet in _interrupt.header
  242 + * consists of the 1394 isochronous packet header, followed by a timestamp
  243 + * quadlet if &fw_cdev_create_iso_context.header_size > 4, followed by quadlets
  244 + * from the packet payload if &fw_cdev_create_iso_context.header_size > 8.
243 245 *
244   - * Behaviour of ver. 1 of this ABI is no longer available since ABI ver. 2.
  246 + * Format of 1394 iso packet header: 16 bits data_length, 2 bits tag, 6 bits
  247 + * channel, 4 bits tcode, 4 bits sy, in big endian byte order.
  248 + * data_length is the actual received size of the packet without the four
  249 + * 1394 iso packet header bytes.
245 250 *
246   - * Format of 1394 iso packet header: 16 bits len, 2 bits tag, 6 bits channel,
247   - * 4 bits tcode, 4 bits sy, in big endian byte order. Format of timestamp:
248   - * 16 bits invalid, 3 bits cycleSeconds, 13 bits cycleCount, in big endian byte
249   - * order.
  251 + * Format of timestamp: 16 bits invalid, 3 bits cycleSeconds, 13 bits
  252 + * cycleCount, in big endian byte order.
  253 + *
  254 + * In version 1 of the ABI, no timestamp quadlet was inserted; instead, payload
  255 + * data followed directly after the 1394 is header if header_size > 4.
  256 + * Behaviour of ver. 1 of this ABI is no longer available since ABI ver. 2.
250 257 */
251 258 struct fw_cdev_event_iso_interrupt {
252 259 __u64 closure;
... ... @@ -257,6 +264,43 @@
257 264 };
258 265  
259 266 /**
  267 + * struct fw_cdev_event_iso_interrupt_mc - An iso buffer chunk was completed
  268 + * @closure: See &fw_cdev_event_common;
  269 + * set by %FW_CDEV_CREATE_ISO_CONTEXT ioctl
  270 + * @type: %FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL
  271 + * @completed: Offset into the receive buffer; data before this offest is valid
  272 + *
  273 + * This event is sent in multichannel contexts (context type
  274 + * %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL) for &fw_cdev_iso_packet buffer
  275 + * chunks that have the %FW_CDEV_ISO_INTERRUPT bit set. Whether this happens
  276 + * when a packet is completed and/or when a buffer chunk is completed depends
  277 + * on the hardware implementation.
  278 + *
  279 + * The buffer is continuously filled with the following data, per packet:
  280 + * - the 1394 iso packet header as described at &fw_cdev_event_iso_interrupt,
  281 + * but in little endian byte order,
  282 + * - packet payload (as many bytes as specified in the data_length field of
  283 + * the 1394 iso packet header) in big endian byte order,
  284 + * - 0...3 padding bytes as needed to align the following trailer quadlet,
  285 + * - trailer quadlet, containing the reception timestamp as described at
  286 + * &fw_cdev_event_iso_interrupt, but in little endian byte order.
  287 + *
  288 + * Hence the per-packet size is data_length (rounded up to a multiple of 4) + 8.
  289 + * When processing the data, stop before a packet that would cross the
  290 + * @completed offset.
  291 + *
  292 + * A packet near the end of a buffer chunk will typically spill over into the
  293 + * next queued buffer chunk. It is the responsibility of the client to check
  294 + * for this condition, assemble a broken-up packet from its parts, and not to
  295 + * re-queue any buffer chunks in which as yet unread packet parts reside.
  296 + */
  297 +struct fw_cdev_event_iso_interrupt_mc {
  298 + __u64 closure;
  299 + __u32 type;
  300 + __u32 completed;
  301 +};
  302 +
  303 +/**
260 304 * struct fw_cdev_event_iso_resource - Iso resources were allocated or freed
261 305 * @closure: See &fw_cdev_event_common;
262 306 * set by %FW_CDEV_IOC_(DE)ALLOCATE_ISO_RESOURCE(_ONCE) ioctl
263 307  
... ... @@ -311,16 +355,18 @@
311 355  
312 356 /**
313 357 * union fw_cdev_event - Convenience union of fw_cdev_event_ types
314   - * @common: Valid for all types
315   - * @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET
316   - * @response: Valid if @common.type == %FW_CDEV_EVENT_RESPONSE
317   - * @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST
318   - * @request2: Valid if @common.type == %FW_CDEV_EVENT_REQUEST2
319   - * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT
320   - * @iso_resource: Valid if @common.type ==
  358 + * @common: Valid for all types
  359 + * @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET
  360 + * @response: Valid if @common.type == %FW_CDEV_EVENT_RESPONSE
  361 + * @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST
  362 + * @request2: Valid if @common.type == %FW_CDEV_EVENT_REQUEST2
  363 + * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT
  364 + * @iso_interrupt_mc: Valid if @common.type ==
  365 + * %FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL
  366 + * @iso_resource: Valid if @common.type ==
321 367 * %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or
322 368 * %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED
323   - * @phy_packet: Valid if @common.type ==
  369 + * @phy_packet: Valid if @common.type ==
324 370 * %FW_CDEV_EVENT_PHY_PACKET_SENT or
325 371 * %FW_CDEV_EVENT_PHY_PACKET_RECEIVED
326 372 *
327 373  
... ... @@ -337,10 +383,11 @@
337 383 struct fw_cdev_event_bus_reset bus_reset;
338 384 struct fw_cdev_event_response response;
339 385 struct fw_cdev_event_request request;
340   - struct fw_cdev_event_request2 request2; /* added in 2.6.36 */
  386 + struct fw_cdev_event_request2 request2; /* added in 2.6.36 */
341 387 struct fw_cdev_event_iso_interrupt iso_interrupt;
342   - struct fw_cdev_event_iso_resource iso_resource; /* added in 2.6.30 */
343   - struct fw_cdev_event_phy_packet phy_packet; /* added in 2.6.36 */
  388 + struct fw_cdev_event_iso_interrupt_mc iso_interrupt_mc; /* added in 2.6.36 */
  389 + struct fw_cdev_event_iso_resource iso_resource; /* added in 2.6.30 */
  390 + struct fw_cdev_event_phy_packet phy_packet; /* added in 2.6.36 */
344 391 };
345 392  
346 393 /* available since kernel version 2.6.22 */
... ... @@ -375,6 +422,7 @@
375 422 /* available since kernel version 2.6.36 */
376 423 #define FW_CDEV_IOC_SEND_PHY_PACKET _IOWR('#', 0x15, struct fw_cdev_send_phy_packet)
377 424 #define FW_CDEV_IOC_RECEIVE_PHY_PACKETS _IOW('#', 0x16, struct fw_cdev_receive_phy_packets)
  425 +#define FW_CDEV_IOC_SET_ISO_CHANNELS _IOW('#', 0x17, struct fw_cdev_set_iso_channels)
378 426  
379 427 /*
380 428 * ABI version history
381 429  
... ... @@ -391,10 +439,13 @@
391 439 * - shared use and auto-response for FCP registers
392 440 * 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable
393 441 * - added %FW_CDEV_IOC_GET_CYCLE_TIMER2
394   - * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2, %FW_CDEV_EVENT_PHY_PACKET_*
  442 + * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2, %FW_CDEV_EVENT_PHY_PACKET_*,
  443 + * and &fw_cdev_allocate.region_end
395 444 * - implemented &fw_cdev_event_bus_reset.bm_node_id
396 445 * - added %FW_CDEV_IOC_SEND_PHY_PACKET, _RECEIVE_PHY_PACKETS
397   - * - added &fw_cdev_allocate.region_end
  446 + * - added %FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL,
  447 + * %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL, and
  448 + * %FW_CDEV_IOC_SET_ISO_CHANNELS
398 449 */
399 450 #define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */
400 451  
401 452  
402 453  
403 454  
404 455  
405 456  
406 457  
407 458  
... ... @@ -597,34 +648,43 @@
597 648 __u32 handle;
598 649 };
599 650  
600   -#define FW_CDEV_ISO_CONTEXT_TRANSMIT 0
601   -#define FW_CDEV_ISO_CONTEXT_RECEIVE 1
  651 +#define FW_CDEV_ISO_CONTEXT_TRANSMIT 0
  652 +#define FW_CDEV_ISO_CONTEXT_RECEIVE 1
  653 +#define FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL 2 /* added in 2.6.36 */
602 654  
603 655 /**
604   - * struct fw_cdev_create_iso_context - Create a context for isochronous IO
605   - * @type: %FW_CDEV_ISO_CONTEXT_TRANSMIT or %FW_CDEV_ISO_CONTEXT_RECEIVE
606   - * @header_size: Header size to strip for receive contexts
607   - * @channel: Channel to bind to
608   - * @speed: Speed for transmit contexts
609   - * @closure: To be returned in &fw_cdev_event_iso_interrupt
  656 + * struct fw_cdev_create_iso_context - Create a context for isochronous I/O
  657 + * @type: %FW_CDEV_ISO_CONTEXT_TRANSMIT or %FW_CDEV_ISO_CONTEXT_RECEIVE or
  658 + * %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL
  659 + * @header_size: Header size to strip in single-channel reception
  660 + * @channel: Channel to bind to in single-channel reception or transmission
  661 + * @speed: Transmission speed
  662 + * @closure: To be returned in &fw_cdev_event_iso_interrupt or
  663 + * &fw_cdev_event_iso_interrupt_multichannel
610 664 * @handle: Handle to context, written back by kernel
611 665 *
612 666 * Prior to sending or receiving isochronous I/O, a context must be created.
613 667 * The context records information about the transmit or receive configuration
614 668 * and typically maps to an underlying hardware resource. A context is set up
615 669 * for either sending or receiving. It is bound to a specific isochronous
616   - * channel.
  670 + * @channel.
617 671 *
618   - * If a context was successfully created, the kernel writes back a handle to the
619   - * context, which must be passed in for subsequent operations on that context.
  672 + * In case of multichannel reception, @header_size and @channel are ignored
  673 + * and the channels are selected by %FW_CDEV_IOC_SET_ISO_CHANNELS.
620 674 *
621   - * For receive contexts, @header_size must be at least 4 and must be a multiple
622   - * of 4.
  675 + * For %FW_CDEV_ISO_CONTEXT_RECEIVE contexts, @header_size must be at least 4
  676 + * and must be a multiple of 4. It is ignored in other context types.
623 677 *
624   - * Note that the effect of a @header_size > 4 depends on
625   - * &fw_cdev_get_info.version, as documented at &fw_cdev_event_iso_interrupt.
  678 + * @speed is ignored in receive context types.
626 679 *
  680 + * If a context was successfully created, the kernel writes back a handle to the
  681 + * context, which must be passed in for subsequent operations on that context.
  682 + *
  683 + * Limitations:
627 684 * No more than one iso context can be created per fd.
  685 + * The total number of contexts that all userspace and kernelspace drivers can
  686 + * create on a card at a time is a hardware limit, typically 4 or 8 contexts per
  687 + * direction, and of them at most one multichannel receive context.
628 688 */
629 689 struct fw_cdev_create_iso_context {
630 690 __u32 type;
... ... @@ -635,6 +695,22 @@
635 695 __u32 handle;
636 696 };
637 697  
  698 +/**
  699 + * struct fw_cdev_set_iso_channels - Select channels in multichannel reception
  700 + * @channels: Bitmask of channels to listen to
  701 + * @handle: Handle of the mutichannel receive context
  702 + *
  703 + * @channels is the bitwise or of 1ULL << n for each channel n to listen to.
  704 + *
  705 + * The ioctl fails with errno %EBUSY if there is already another receive context
  706 + * on a channel in @channels. In that case, the bitmask of all unoccupied
  707 + * channels is returned in @channels.
  708 + */
  709 +struct fw_cdev_set_iso_channels {
  710 + __u64 channels;
  711 + __u32 handle;
  712 +};
  713 +
638 714 #define FW_CDEV_ISO_PAYLOAD_LENGTH(v) (v)
639 715 #define FW_CDEV_ISO_INTERRUPT (1 << 16)
640 716 #define FW_CDEV_ISO_SKIP (1 << 17)
641 717  
642 718  
643 719  
644 720  
645 721  
646 722  
647 723  
... ... @@ -645,42 +721,72 @@
645 721  
646 722 /**
647 723 * struct fw_cdev_iso_packet - Isochronous packet
648   - * @control: Contains the header length (8 uppermost bits), the sy field
649   - * (4 bits), the tag field (2 bits), a sync flag (1 bit),
650   - * a skip flag (1 bit), an interrupt flag (1 bit), and the
  724 + * @control: Contains the header length (8 uppermost bits),
  725 + * the sy field (4 bits), the tag field (2 bits), a sync flag
  726 + * or a skip flag (1 bit), an interrupt flag (1 bit), and the
651 727 * payload length (16 lowermost bits)
652   - * @header: Header and payload
  728 + * @header: Header and payload in case of a transmit context.
653 729 *
654 730 * &struct fw_cdev_iso_packet is used to describe isochronous packet queues.
655   - *
656 731 * Use the FW_CDEV_ISO_ macros to fill in @control.
  732 + * The @header array is empty in case of receive contexts.
657 733 *
658   - * For transmit packets, the header length must be a multiple of 4 and specifies
659   - * the numbers of bytes in @header that will be prepended to the packet's
660   - * payload; these bytes are copied into the kernel and will not be accessed
661   - * after the ioctl has returned. The sy and tag fields are copied to the iso
662   - * packet header (these fields are specified by IEEE 1394a and IEC 61883-1).
663   - * The skip flag specifies that no packet is to be sent in a frame; when using
664   - * this, all other fields except the interrupt flag must be zero.
  734 + * Context type %FW_CDEV_ISO_CONTEXT_TRANSMIT:
665 735 *
666   - * For receive packets, the header length must be a multiple of the context's
667   - * header size; if the header length is larger than the context's header size,
668   - * multiple packets are queued for this entry. The sy and tag fields are
669   - * ignored. If the sync flag is set, the context drops all packets until
670   - * a packet with a matching sy field is received (the sync value to wait for is
671   - * specified in the &fw_cdev_start_iso structure). The payload length defines
672   - * how many payload bytes can be received for one packet (in addition to payload
673   - * quadlets that have been defined as headers and are stripped and returned in
674   - * the &fw_cdev_event_iso_interrupt structure). If more bytes are received, the
675   - * additional bytes are dropped. If less bytes are received, the remaining
676   - * bytes in this part of the payload buffer will not be written to, not even by
677   - * the next packet, i.e., packets received in consecutive frames will not
678   - * necessarily be consecutive in memory. If an entry has queued multiple
679   - * packets, the payload length is divided equally among them.
  736 + * @control.HEADER_LENGTH must be a multiple of 4. It specifies the numbers of
  737 + * bytes in @header that will be prepended to the packet's payload. These bytes
  738 + * are copied into the kernel and will not be accessed after the ioctl has
  739 + * returned.
680 740 *
681   - * When a packet with the interrupt flag set has been completed, the
  741 + * The @control.SY and TAG fields are copied to the iso packet header. These
  742 + * fields are specified by IEEE 1394a and IEC 61883-1.
  743 + *
  744 + * The @control.SKIP flag specifies that no packet is to be sent in a frame.
  745 + * When using this, all other fields except @control.INTERRUPT must be zero.
  746 + *
  747 + * When a packet with the @control.INTERRUPT flag set has been completed, an
  748 + * &fw_cdev_event_iso_interrupt event will be sent.
  749 + *
  750 + * Context type %FW_CDEV_ISO_CONTEXT_RECEIVE:
  751 + *
  752 + * @control.HEADER_LENGTH must be a multiple of the context's header_size.
  753 + * If the HEADER_LENGTH is larger than the context's header_size, multiple
  754 + * packets are queued for this entry.
  755 + *
  756 + * The @control.SY and TAG fields are ignored.
  757 + *
  758 + * If the @control.SYNC flag is set, the context drops all packets until a
  759 + * packet with a sy field is received which matches &fw_cdev_start_iso.sync.
  760 + *
  761 + * @control.PAYLOAD_LENGTH defines how many payload bytes can be received for
  762 + * one packet (in addition to payload quadlets that have been defined as headers
  763 + * and are stripped and returned in the &fw_cdev_event_iso_interrupt structure).
  764 + * If more bytes are received, the additional bytes are dropped. If less bytes
  765 + * are received, the remaining bytes in this part of the payload buffer will not
  766 + * be written to, not even by the next packet. I.e., packets received in
  767 + * consecutive frames will not necessarily be consecutive in memory. If an
  768 + * entry has queued multiple packets, the PAYLOAD_LENGTH is divided equally
  769 + * among them.
  770 + *
  771 + * When a packet with the @control.INTERRUPT flag set has been completed, an
682 772 * &fw_cdev_event_iso_interrupt event will be sent. An entry that has queued
683 773 * multiple receive packets is completed when its last packet is completed.
  774 + *
  775 + * Context type %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
  776 + *
  777 + * Here, &fw_cdev_iso_packet would be more aptly named _iso_buffer_chunk since
  778 + * it specifies a chunk of the mmap()'ed buffer, while the number and alignment
  779 + * of packets to be placed into the buffer chunk is not known beforehand.
  780 + *
  781 + * @control.PAYLOAD_LENGTH is the size of the buffer chunk and specifies room
  782 + * for header, payload, padding, and trailer bytes of one or more packets.
  783 + * It must be a multiple of 4.
  784 + *
  785 + * @control.HEADER_LENGTH, TAG and SY are ignored. SYNC is treated as described
  786 + * for single-channel reception.
  787 + *
  788 + * When a buffer chunk with the @control.INTERRUPT flag set has been filled
  789 + * entirely, an &fw_cdev_event_iso_interrupt_mc event will be sent.
684 790 */
685 791 struct fw_cdev_iso_packet {
686 792 __u32 control;
687 793  
... ... @@ -689,9 +795,9 @@
689 795  
690 796 /**
691 797 * struct fw_cdev_queue_iso - Queue isochronous packets for I/O
692   - * @packets: Userspace pointer to packet data
  798 + * @packets: Userspace pointer to an array of &fw_cdev_iso_packet
693 799 * @data: Pointer into mmap()'ed payload buffer
694   - * @size: Size of packet data in bytes
  800 + * @size: Size of the @packets array, in bytes
695 801 * @handle: Isochronous context handle
696 802 *
697 803 * Queue a number of isochronous packets for reception or transmission.
... ... @@ -704,6 +810,9 @@
704 810 * The kernel may or may not queue all packets, but will write back updated
705 811 * values of the @packets, @data and @size fields, so the ioctl can be
706 812 * resubmitted easily.
  813 + *
  814 + * In case of a multichannel receive context, @data must be quadlet-aligned
  815 + * relative to the buffer start.
707 816 */
708 817 struct fw_cdev_queue_iso {
709 818 __u64 packets;
include/linux/firewire.h
... ... @@ -372,17 +372,19 @@
372 372 * scatter-gather streaming (e.g. assembling video frame automatically).
373 373 */
374 374 struct fw_iso_packet {
375   - u16 payload_length; /* Length of indirect payload. */
376   - u32 interrupt:1; /* Generate interrupt on this packet */
377   - u32 skip:1; /* Set to not send packet at all. */
378   - u32 tag:2;
379   - u32 sy:4;
380   - u32 header_length:8; /* Length of immediate header. */
381   - u32 header[0];
  375 + u16 payload_length; /* Length of indirect payload */
  376 + u32 interrupt:1; /* Generate interrupt on this packet */
  377 + u32 skip:1; /* tx: Set to not send packet at all */
  378 + /* rx: Sync bit, wait for matching sy */
  379 + u32 tag:2; /* tx: Tag in packet header */
  380 + u32 sy:4; /* tx: Sy in packet header */
  381 + u32 header_length:8; /* Length of immediate header */
  382 + u32 header[0]; /* tx: Top of 1394 isoch. data_block */
382 383 };
383 384  
384   -#define FW_ISO_CONTEXT_TRANSMIT 0
385   -#define FW_ISO_CONTEXT_RECEIVE 1
  385 +#define FW_ISO_CONTEXT_TRANSMIT 0
  386 +#define FW_ISO_CONTEXT_RECEIVE 1
  387 +#define FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL 2
386 388  
387 389 #define FW_ISO_CONTEXT_MATCH_TAG0 1
388 390 #define FW_ISO_CONTEXT_MATCH_TAG1 2
389 391  
390 392  
391 393  
... ... @@ -406,24 +408,31 @@
406 408 int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card,
407 409 int page_count, enum dma_data_direction direction);
408 410 void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card);
  411 +size_t fw_iso_buffer_lookup(struct fw_iso_buffer *buffer, dma_addr_t completed);
409 412  
410 413 struct fw_iso_context;
411 414 typedef void (*fw_iso_callback_t)(struct fw_iso_context *context,
412 415 u32 cycle, size_t header_length,
413 416 void *header, void *data);
  417 +typedef void (*fw_iso_mc_callback_t)(struct fw_iso_context *context,
  418 + dma_addr_t completed, void *data);
414 419 struct fw_iso_context {
415 420 struct fw_card *card;
416 421 int type;
417 422 int channel;
418 423 int speed;
419 424 size_t header_size;
420   - fw_iso_callback_t callback;
  425 + union {
  426 + fw_iso_callback_t sc;
  427 + fw_iso_mc_callback_t mc;
  428 + } callback;
421 429 void *callback_data;
422 430 };
423 431  
424 432 struct fw_iso_context *fw_iso_context_create(struct fw_card *card,
425 433 int type, int channel, int speed, size_t header_size,
426 434 fw_iso_callback_t callback, void *callback_data);
  435 +int fw_iso_context_set_channels(struct fw_iso_context *ctx, u64 *channels);
427 436 int fw_iso_context_queue(struct fw_iso_context *ctx,
428 437 struct fw_iso_packet *packet,
429 438 struct fw_iso_buffer *buffer,