]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 29 Aug 2010 15:19:02 +0000 (08:19 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 29 Aug 2010 15:19:02 +0000 (08:19 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6:
  firewire: ohci: work around VIA and NEC PHY packet reception bug
  firewire: core: do not use del_timer_sync() in interrupt context
  firewire: net: fix unicast reception RCODE in failure paths
  firewire: sbp2: fix stall with "Unsolicited response"
  firewire: sbp2: fix memory leak in sbp2_cancel_orbs or at send error
  ieee1394: Adjust confusing if indentation

drivers/firewire/core-transaction.c
drivers/firewire/net.c
drivers/firewire/ohci.c
drivers/firewire/sbp2.c
drivers/ieee1394/ohci1394.c

index ca7ca56661e018c5ecfd9d4c56321f4dea901f93..b42a0bde8494bf0dec8cc2e20d34dfc3e7c046b5 100644 (file)
@@ -81,6 +81,10 @@ static int close_transaction(struct fw_transaction *transaction,
        spin_lock_irqsave(&card->lock, flags);
        list_for_each_entry(t, &card->transaction_list, link) {
                if (t == transaction) {
+                       if (!del_timer(&t->split_timeout_timer)) {
+                               spin_unlock_irqrestore(&card->lock, flags);
+                               goto timed_out;
+                       }
                        list_del_init(&t->link);
                        card->tlabel_mask &= ~(1ULL << t->tlabel);
                        break;
@@ -89,11 +93,11 @@ static int close_transaction(struct fw_transaction *transaction,
        spin_unlock_irqrestore(&card->lock, flags);
 
        if (&t->link != &card->transaction_list) {
-               del_timer_sync(&t->split_timeout_timer);
                t->callback(card, rcode, NULL, 0, t->callback_data);
                return 0;
        }
 
+ timed_out:
        return -ENOENT;
 }
 
@@ -921,6 +925,10 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
        spin_lock_irqsave(&card->lock, flags);
        list_for_each_entry(t, &card->transaction_list, link) {
                if (t->node_id == source && t->tlabel == tlabel) {
+                       if (!del_timer(&t->split_timeout_timer)) {
+                               spin_unlock_irqrestore(&card->lock, flags);
+                               goto timed_out;
+                       }
                        list_del_init(&t->link);
                        card->tlabel_mask &= ~(1ULL << t->tlabel);
                        break;
@@ -929,6 +937,7 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
        spin_unlock_irqrestore(&card->lock, flags);
 
        if (&t->link == &card->transaction_list) {
+ timed_out:
                fw_notify("Unsolicited response (source %x, tlabel %x)\n",
                          source, tlabel);
                return;
@@ -963,8 +972,6 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
                break;
        }
 
-       del_timer_sync(&t->split_timeout_timer);
-
        /*
         * The response handler may be executed while the request handler
         * is still pending.  Cancel the request handler.
index da17d409a244b0af97249341855dfe301b506ab3..33f8421c71cc05001c57bbf275b61679fded72eb 100644 (file)
@@ -579,7 +579,7 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
                if (!peer) {
                        fw_notify("No peer for ARP packet from %016llx\n",
                                  (unsigned long long)peer_guid);
-                       goto failed_proto;
+                       goto no_peer;
                }
 
                /*
@@ -656,7 +656,7 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
 
        return 0;
 
failed_proto:
no_peer:
        net->stats.rx_errors++;
        net->stats.rx_dropped++;
 
@@ -664,7 +664,7 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
        if (netif_queue_stopped(net))
                netif_wake_queue(net);
 
-       return 0;
+       return -ENOENT;
 }
 
 static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
@@ -701,7 +701,7 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
                        fw_error("out of memory\n");
                        net->stats.rx_dropped++;
 
-                       return -1;
+                       return -ENOMEM;
                }
                skb_reserve(skb, (net->hard_header_len + 15) & ~15);
                memcpy(skb_put(skb, len), buf, len);
@@ -726,8 +726,10 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
        spin_lock_irqsave(&dev->lock, flags);
 
        peer = fwnet_peer_find_by_node_id(dev, source_node_id, generation);
-       if (!peer)
-               goto bad_proto;
+       if (!peer) {
+               retval = -ENOENT;
+               goto fail;
+       }
 
        pd = fwnet_pd_find(peer, datagram_label);
        if (pd == NULL) {
@@ -741,7 +743,7 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
                                  dg_size, buf, fg_off, len);
                if (pd == NULL) {
                        retval = -ENOMEM;
-                       goto bad_proto;
+                       goto fail;
                }
                peer->pdg_size++;
        } else {
@@ -755,9 +757,9 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
                        pd = fwnet_pd_new(net, peer, datagram_label,
                                          dg_size, buf, fg_off, len);
                        if (pd == NULL) {
-                               retval = -ENOMEM;
                                peer->pdg_size--;
-                               goto bad_proto;
+                               retval = -ENOMEM;
+                               goto fail;
                        }
                } else {
                        if (!fwnet_pd_update(peer, pd, buf, fg_off, len)) {
@@ -768,7 +770,8 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
                                 */
                                fwnet_pd_delete(pd);
                                peer->pdg_size--;
-                               goto bad_proto;
+                               retval = -ENOMEM;
+                               goto fail;
                        }
                }
        } /* new datagram or add to existing one */
@@ -794,14 +797,13 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
        spin_unlock_irqrestore(&dev->lock, flags);
 
        return 0;
-
- bad_proto:
+ fail:
        spin_unlock_irqrestore(&dev->lock, flags);
 
        if (netif_queue_stopped(net))
                netif_wake_queue(net);
 
-       return 0;
+       return retval;
 }
 
 static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r,
index 7f03540cabe8b3932021545a6db05aebb3f729b1..be29b0bb247101442a63fa623467e98ad7b77524 100644 (file)
@@ -694,7 +694,15 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
        log_ar_at_event('R', p.speed, p.header, evt);
 
        /*
-        * The OHCI bus reset handler synthesizes a phy packet with
+        * Several controllers, notably from NEC and VIA, forget to
+        * write ack_complete status at PHY packet reception.
+        */
+       if (evt == OHCI1394_evt_no_status &&
+           (p.header[0] & 0xff) == (OHCI1394_phy_tcode << 4))
+               p.ack = ACK_COMPLETE;
+
+       /*
+        * The OHCI bus reset handler synthesizes a PHY packet with
         * the new generation number when a bus reset happens (see
         * section 8.4.2.3).  This helps us determine when a request
         * was received and make sure we send the response in the same
index 9f76171717e50302dc4e895a4988cb15f7e7023f..bfae4b309791103e48b2bb704300d1cd84da9750 100644 (file)
@@ -450,7 +450,7 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request,
 
        if (&orb->link != &lu->orb_list) {
                orb->callback(orb, &status);
-               kref_put(&orb->kref, free_orb);
+               kref_put(&orb->kref, free_orb); /* orb callback reference */
        } else {
                fw_error("status write for unknown orb\n");
        }
@@ -472,20 +472,28 @@ static void complete_transaction(struct fw_card *card, int rcode,
         * So this callback only sets the rcode if it hasn't already
         * been set and only does the cleanup if the transaction
         * failed and we didn't already get a status write.
+        *
+        * Here we treat RCODE_CANCELLED like RCODE_COMPLETE because some
+        * OXUF936QSE firmwares occasionally respond after Split_Timeout and
+        * complete the ORB just fine.  Note, we also get RCODE_CANCELLED
+        * from sbp2_cancel_orbs() if fw_cancel_transaction() == 0.
         */
        spin_lock_irqsave(&card->lock, flags);
 
        if (orb->rcode == -1)
                orb->rcode = rcode;
-       if (orb->rcode != RCODE_COMPLETE) {
+
+       if (orb->rcode != RCODE_COMPLETE && orb->rcode != RCODE_CANCELLED) {
                list_del(&orb->link);
                spin_unlock_irqrestore(&card->lock, flags);
+
                orb->callback(orb, NULL);
+               kref_put(&orb->kref, free_orb); /* orb callback reference */
        } else {
                spin_unlock_irqrestore(&card->lock, flags);
        }
 
-       kref_put(&orb->kref, free_orb);
+       kref_put(&orb->kref, free_orb); /* transaction callback reference */
 }
 
 static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
@@ -501,9 +509,8 @@ static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
        list_add_tail(&orb->link, &lu->orb_list);
        spin_unlock_irqrestore(&device->card->lock, flags);
 
-       /* Take a ref for the orb list and for the transaction callback. */
-       kref_get(&orb->kref);
-       kref_get(&orb->kref);
+       kref_get(&orb->kref); /* transaction callback reference */
+       kref_get(&orb->kref); /* orb callback reference */
 
        fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
                        node_id, generation, device->max_speed, offset,
@@ -525,11 +532,11 @@ static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu)
 
        list_for_each_entry_safe(orb, next, &list, link) {
                retval = 0;
-               if (fw_cancel_transaction(device->card, &orb->t) == 0)
-                       continue;
+               fw_cancel_transaction(device->card, &orb->t);
 
                orb->rcode = RCODE_CANCELLED;
                orb->callback(orb, NULL);
+               kref_put(&orb->kref, free_orb); /* orb callback reference */
        }
 
        return retval;
index d0dc1db80b295adc31ad88eb38bb82a3106f6175..50815022cff1dccc4a285d70a9b58d5760315175 100644 (file)
@@ -1106,7 +1106,7 @@ static int ohci_iso_recv_init(struct hpsb_iso *iso)
                if (recv->block_irq_interval * 4 > iso->buf_packets)
                        recv->block_irq_interval = iso->buf_packets / 4;
                if (recv->block_irq_interval < 1)
-               recv->block_irq_interval = 1;
+                       recv->block_irq_interval = 1;
 
                /* choose a buffer stride */
                /* must be a power of 2, and <= PAGE_SIZE */