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

Commit c3ca48f0 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: core: ignore link-active bit of new nodes, fix device recognition
  firewire: sbp2: revert obsolete 'fix stall with "Unsolicited response"'
  firewire: core: increase default SPLIT_TIMEOUT value
  firewire: ohci: Misleading kfree in ohci.c::pci_probe/remove
  firewire: ohci: omit IntEvent.busReset check rom AT queueing
  firewire: ohci: prevent starting of iso contexts with empty queue
  firewire: ohci: prevent iso completion callbacks after context stop
  firewire: core: rename some variables
  firewire: nosy: should work on Power Mac G4 PCI too
  firewire: core: fix card->reset_jiffies overflow
  firewire: cdev: remove unneeded reference
  firewire: cdev: always wait for outbound transactions to complete
  firewire: cdev: remove unneeded idr_find() from complete_transaction()
  firewire: ohci: log dead DMA contexts
parents 4e76ae44 115881d3
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -75,7 +75,8 @@ config FIREWIRE_NOSY
	  The following cards are known to be based on PCILynx or PCILynx-2:
	  IOI IOI-1394TT (PCI card), Unibrain Fireboard 400 PCI Lynx-2
	  (PCI card), Newer Technology FireWire 2 Go (CardBus card),
	  Apple Power Mac G3 blue & white (onboard controller).
	  Apple Power Mac G3 blue & white and G4 with PCI graphics
	  (onboard controller).

	  To compile this driver as a module, say M here:  The module will be
	  called nosy.  Source code of a userspace interface to nosy, called
+15 −6
Original line number Diff line number Diff line
@@ -75,6 +75,13 @@ static size_t config_rom_length = 1 + 4 + 1 + 1;
#define BIB_IRMC		((1) << 31)
#define NODE_CAPABILITIES	0x0c0083c0 /* per IEEE 1394 clause 8.3.2.6.5.2 */

/*
 * IEEE-1394 specifies a default SPLIT_TIMEOUT value of 800 cycles (100 ms),
 * but we have to make it longer because there are many devices whose firmware
 * is just too slow for that.
 */
#define DEFAULT_SPLIT_TIMEOUT	(2 * 8000)

#define CANON_OUI		0x000085

static void generate_config_rom(struct fw_card *card, __be32 *config_rom)
@@ -233,7 +240,7 @@ static void br_work(struct work_struct *work)

	/* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */
	if (card->reset_jiffies != 0 &&
	    time_is_after_jiffies(card->reset_jiffies + 2 * HZ)) {
	    time_before64(get_jiffies_64(), card->reset_jiffies + 2 * HZ)) {
		if (!schedule_delayed_work(&card->br_work, 2 * HZ))
			fw_card_put(card);
		return;
@@ -316,7 +323,8 @@ static void bm_work(struct work_struct *work)
	irm_id   = card->irm_node->node_id;
	local_id = card->local_node->node_id;

	grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 8));
	grace = time_after64(get_jiffies_64(),
			     card->reset_jiffies + DIV_ROUND_UP(HZ, 8));

	if ((is_next_generation(generation, card->bm_generation) &&
	     !card->bm_abdicate) ||
@@ -511,10 +519,11 @@ void fw_card_initialize(struct fw_card *card,
	card->device = device;
	card->current_tlabel = 0;
	card->tlabel_mask = 0;
	card->split_timeout_hi = 0;
	card->split_timeout_lo = 800 << 19;
	card->split_timeout_cycles = 800;
	card->split_timeout_jiffies = DIV_ROUND_UP(HZ, 10);
	card->split_timeout_hi = DEFAULT_SPLIT_TIMEOUT / 8000;
	card->split_timeout_lo = (DEFAULT_SPLIT_TIMEOUT % 8000) << 19;
	card->split_timeout_cycles = DEFAULT_SPLIT_TIMEOUT;
	card->split_timeout_jiffies =
			DIV_ROUND_UP(DEFAULT_SPLIT_TIMEOUT * HZ, 8000);
	card->color = 0;
	card->broadcast_channel = BROADCAST_CHANNEL_INITIAL;

+29 −25
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ struct client {
	struct idr resource_idr;
	struct list_head event_list;
	wait_queue_head_t wait;
	wait_queue_head_t tx_flush_wait;
	u64 bus_reset_closure;

	struct fw_iso_context *iso_context;
@@ -251,6 +252,7 @@ static int fw_device_op_open(struct inode *inode, struct file *file)
	idr_init(&client->resource_idr);
	INIT_LIST_HEAD(&client->event_list);
	init_waitqueue_head(&client->wait);
	init_waitqueue_head(&client->tx_flush_wait);
	INIT_LIST_HEAD(&client->phy_receiver_link);
	kref_init(&client->kref);

@@ -520,10 +522,6 @@ static int release_client_resource(struct client *client, u32 handle,
static void release_transaction(struct client *client,
				struct client_resource *resource)
{
	struct outbound_transaction_resource *r = container_of(resource,
			struct outbound_transaction_resource, resource);

	fw_cancel_transaction(client->device->card, &r->transaction);
}

static void complete_transaction(struct fw_card *card, int rcode,
@@ -540,22 +538,9 @@ static void complete_transaction(struct fw_card *card, int rcode,
		memcpy(rsp->data, payload, rsp->length);

	spin_lock_irqsave(&client->lock, flags);
	/*
	 * 1. If called while in shutdown, the idr tree must be left untouched.
	 *    The idr handle will be removed and the client reference will be
	 *    dropped later.
	 * 2. If the call chain was release_client_resource ->
	 *    release_transaction -> complete_transaction (instead of a normal
	 *    conclusion of the transaction), i.e. if this resource was already
	 *    unregistered from the idr, the client reference will be dropped
	 *    by release_client_resource and we must not drop it here.
	 */
	if (!client->in_shutdown &&
	    idr_find(&client->resource_idr, e->r.resource.handle)) {
	idr_remove(&client->resource_idr, e->r.resource.handle);
		/* Drop the idr's reference */
		client_put(client);
	}
	if (client->in_shutdown)
		wake_up(&client->tx_flush_wait);
	spin_unlock_irqrestore(&client->lock, flags);

	rsp->type = FW_CDEV_EVENT_RESPONSE;
@@ -575,7 +560,7 @@ static void complete_transaction(struct fw_card *card, int rcode,
		queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length,
			    NULL, 0);

	/* Drop the transaction callback's reference */
	/* Drop the idr's reference */
	client_put(client);
}

@@ -614,9 +599,6 @@ static int init_request(struct client *client,
	if (ret < 0)
		goto failed;

	/* Get a reference for the transaction callback */
	client_get(client);

	fw_send_request(client->device->card, &e->r.transaction,
			request->tcode, destination_id, request->generation,
			speed, request->offset, e->response.data,
@@ -1223,7 +1205,8 @@ static void iso_resource_work(struct work_struct *work)
	todo = r->todo;
	/* Allow 1000ms grace period for other reallocations. */
	if (todo == ISO_RES_ALLOC &&
	    time_is_after_jiffies(client->device->card->reset_jiffies + HZ)) {
	    time_before64(get_jiffies_64(),
			  client->device->card->reset_jiffies + HZ)) {
		schedule_iso_resource(r, DIV_ROUND_UP(HZ, 3));
		skip = true;
	} else {
@@ -1678,6 +1661,25 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma)
	return ret;
}

static int is_outbound_transaction_resource(int id, void *p, void *data)
{
	struct client_resource *resource = p;

	return resource->release == release_transaction;
}

static int has_outbound_transactions(struct client *client)
{
	int ret;

	spin_lock_irq(&client->lock);
	ret = idr_for_each(&client->resource_idr,
			   is_outbound_transaction_resource, NULL);
	spin_unlock_irq(&client->lock);

	return ret;
}

static int shutdown_resource(int id, void *p, void *data)
{
	struct client_resource *resource = p;
@@ -1713,6 +1715,8 @@ static int fw_device_op_release(struct inode *inode, struct file *file)
	client->in_shutdown = true;
	spin_unlock_irq(&client->lock);

	wait_event(client->tx_flush_wait, !has_outbound_transactions(client));

	idr_for_each(&client->resource_idr, shutdown_resource, client);
	idr_remove_all(&client->resource_idr);
	idr_destroy(&client->resource_idr);
+14 −8
Original line number Diff line number Diff line
@@ -747,7 +747,8 @@ static void fw_device_shutdown(struct work_struct *work)
		container_of(work, struct fw_device, work.work);
	int minor = MINOR(device->device.devt);

	if (time_is_after_jiffies(device->card->reset_jiffies + SHUTDOWN_DELAY)
	if (time_before64(get_jiffies_64(),
			  device->card->reset_jiffies + SHUTDOWN_DELAY)
	    && !list_empty(&device->card->link)) {
		schedule_delayed_work(&device->work, SHUTDOWN_DELAY);
		return;
@@ -954,6 +955,7 @@ static void fw_device_init(struct work_struct *work)
			device->config_rom_retries++;
			schedule_delayed_work(&device->work, RETRY_DELAY);
		} else {
			if (device->node->link_on)
				fw_notify("giving up on config rom for node id %x\n",
					  device->node_id);
			if (device->node == device->card->root_node)
@@ -1168,9 +1170,12 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)

	switch (event) {
	case FW_NODE_CREATED:
	case FW_NODE_LINK_ON:
		if (!node->link_on)
			break;
		/*
		 * Attempt to scan the node, regardless whether its self ID has
		 * the L (link active) flag set or not.  Some broken devices
		 * send L=0 but have an up-and-running link; others send L=1
		 * without actually having a link.
		 */
 create:
		device = kzalloc(sizeof(*device), GFP_ATOMIC);
		if (device == NULL)
@@ -1213,6 +1218,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
		break;

	case FW_NODE_INITIATED_RESET:
	case FW_NODE_LINK_ON:
		device = node->data;
		if (device == NULL)
			goto create;
@@ -1230,10 +1236,10 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
		break;

	case FW_NODE_UPDATED:
		if (!node->link_on || node->data == NULL)
		device = node->data;
		if (device == NULL)
			break;

		device = node->data;
		device->node_id = node->node_id;
		smp_wmb();  /* update node_id before generation */
		device->generation = card->generation;
+11 −11
Original line number Diff line number Diff line
@@ -235,45 +235,45 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation,
static int manage_channel(struct fw_card *card, int irm_id, int generation,
		u32 channels_mask, u64 offset, bool allocate, __be32 data[2])
{
	__be32 c, all, old;
	int i, ret = -EIO, retry = 5;
	__be32 bit, all, old;
	int channel, ret = -EIO, retry = 5;

	old = all = allocate ? cpu_to_be32(~0) : 0;

	for (i = 0; i < 32; i++) {
		if (!(channels_mask & 1 << i))
	for (channel = 0; channel < 32; channel++) {
		if (!(channels_mask & 1 << channel))
			continue;

		ret = -EBUSY;

		c = cpu_to_be32(1 << (31 - i));
		if ((old & c) != (all & c))
		bit = cpu_to_be32(1 << (31 - channel));
		if ((old & bit) != (all & bit))
			continue;

		data[0] = old;
		data[1] = old ^ c;
		data[1] = old ^ bit;
		switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
					   irm_id, generation, SCODE_100,
					   offset, data, 8)) {
		case RCODE_GENERATION:
			/* A generation change frees all channels. */
			return allocate ? -EAGAIN : i;
			return allocate ? -EAGAIN : channel;

		case RCODE_COMPLETE:
			if (data[0] == old)
				return i;
				return channel;

			old = data[0];

			/* Is the IRM 1394a-2000 compliant? */
			if ((data[0] & c) == (data[1] & c))
			if ((data[0] & bit) == (data[1] & bit))
				continue;

			/* 1394-1995 IRM, fall through to retry. */
		default:
			if (retry) {
				retry--;
				i--;
				channel--;
			} else {
				ret = -EIO;
			}
Loading