]> Pileus Git - ~andy/linux/blobdiff - drivers/firewire/fw-ohci.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[~andy/linux] / drivers / firewire / fw-ohci.c
index 4c7cf15986aecbccbbfd4184eece3de7c5b405b2..1180d0be0bb4c0536cd7917cbd68910518f67450 100644 (file)
@@ -205,6 +205,7 @@ struct fw_ohci {
 
        u32 it_context_mask;
        struct iso_context *it_context_list;
+       u64 ir_context_channels;
        u32 ir_context_mask;
        struct iso_context *ir_context_list;
 };
@@ -935,7 +936,9 @@ static int at_context_queue_packet(struct context *ctx,
         */
 
        header = (__le32 *) &d[1];
-       if (packet->header_length > 8) {
+       switch (packet->header_length) {
+       case 16:
+       case 12:
                header[0] = cpu_to_le32((packet->header[0] & 0xffff) |
                                        (packet->speed << 16));
                header[1] = cpu_to_le32((packet->header[1] & 0xffff) |
@@ -949,12 +952,27 @@ static int at_context_queue_packet(struct context *ctx,
                        header[3] = (__force __le32) packet->header[3];
 
                d[0].req_count = cpu_to_le16(packet->header_length);
-       } else {
+               break;
+
+       case 8:
                header[0] = cpu_to_le32((OHCI1394_phy_tcode << 4) |
                                        (packet->speed << 16));
                header[1] = cpu_to_le32(packet->header[0]);
                header[2] = cpu_to_le32(packet->header[1]);
                d[0].req_count = cpu_to_le16(12);
+               break;
+
+       case 4:
+               header[0] = cpu_to_le32((packet->header[0] & 0xffff) |
+                                       (packet->speed << 16));
+               header[1] = cpu_to_le32(packet->header[0] & 0xffff0000);
+               d[0].req_count = cpu_to_le16(8);
+               break;
+
+       default:
+               /* BUG(); */
+               packet->ack = RCODE_SEND_ERROR;
+               return -1;
        }
 
        driver_data = (struct driver_data *) &d[3];
@@ -1877,20 +1895,23 @@ static int handle_it_packet(struct context *context,
 }
 
 static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
-                                               int type, size_t header_size)
+                               int type, int channel, size_t header_size)
 {
        struct fw_ohci *ohci = fw_ohci(card);
        struct iso_context *ctx, *list;
        descriptor_callback_t callback;
+       u64 *channels, dont_care = ~0ULL;
        u32 *mask, regs;
        unsigned long flags;
        int index, ret = -ENOMEM;
 
        if (type == FW_ISO_CONTEXT_TRANSMIT) {
+               channels = &dont_care;
                mask = &ohci->it_context_mask;
                list = ohci->it_context_list;
                callback = handle_it_packet;
        } else {
+               channels = &ohci->ir_context_channels;
                mask = &ohci->ir_context_mask;
                list = ohci->ir_context_list;
                if (ohci->use_dualbuffer)
@@ -1900,9 +1921,11 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
        }
 
        spin_lock_irqsave(&ohci->lock, flags);
-       index = ffs(*mask) - 1;
-       if (index >= 0)
+       index = *channels & 1ULL << channel ? ffs(*mask) - 1 : -1;
+       if (index >= 0) {
+               *channels &= ~(1ULL << channel);
                *mask &= ~(1 << index);
+       }
        spin_unlock_irqrestore(&ohci->lock, flags);
 
        if (index < 0)
@@ -2012,6 +2035,7 @@ static void ohci_free_iso_context(struct fw_iso_context *base)
        } else {
                index = ctx - ohci->ir_context_list;
                ohci->ir_context_mask |= 1 << index;
+               ohci->ir_context_channels |= 1ULL << base->channel;
        }
 
        spin_unlock_irqrestore(&ohci->lock, flags);
@@ -2424,6 +2448,7 @@ static int __devinit pci_probe(struct pci_dev *dev,
        ohci->it_context_list = kzalloc(size, GFP_KERNEL);
 
        reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0);
+       ohci->ir_context_channels = ~0ULL;
        ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
        reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0);
        size = sizeof(struct iso_context) * hweight32(ohci->ir_context_mask);
@@ -2451,11 +2476,12 @@ static int __devinit pci_probe(struct pci_dev *dev,
                reg_read(ohci, OHCI1394_GUIDLo);
 
        err = fw_card_add(&ohci->card, max_receive, link_speed, guid);
-       if (err < 0)
+       if (err)
                goto fail_self_id;
 
        fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n",
                  dev_name(&dev->dev), version >> 16, version & 0xff);
+
        return 0;
 
  fail_self_id: