Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 994b384a authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
parents 29cfcddc a4dc090b
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -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.
+15 −13
Original line number Diff line number Diff line
@@ -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,
+9 −1
Original line number Diff line number Diff line
@@ -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
+15 −8
Original line number Diff line number Diff line
@@ -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;
+1 −1

File changed.

Contains only whitespace changes.