sound/firewire/dice/dice-transaction.c

Source file repositories/reference/linux-study-clean/sound/firewire/dice/dice-transaction.c

File Facts

System
Linux kernel
Corpus path
sound/firewire/dice/dice-transaction.c
Extension
.c
Size
8713 bytes
Lines
369
Domain
Driver Families
Bucket
sound/firewire
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (err == 0) {
			/* success */
			if (buffer[0] == cpu_to_be64(OWNER_NO_OWNER))
				break;
			/* The address seems to be already registered. */
			if (buffer[0] == buffer[1])
				break;

			dev_err(&dice->unit->device,
				"device is already in use\n");
			err = -EBUSY;
		}
		if (err != -EAGAIN || retries-- > 0)
			break;

		msleep(20);
	}

	kfree(buffer);

	if (err < 0)
		dice->owner_generation = -1;

	return err;
}

static void unregister_notification_address(struct snd_dice *dice)
{
	struct fw_device *device = fw_parent_device(dice->unit);
	__be64 *buffer;

	buffer = kmalloc(2 * 8, GFP_KERNEL);
	if (buffer == NULL)
		return;

	buffer[0] = cpu_to_be64(
		((u64)device->card->node_id << OWNER_NODE_SHIFT) |
		dice->notification_handler.offset);
	buffer[1] = cpu_to_be64(OWNER_NO_OWNER);
	snd_fw_transaction(dice->unit, TCODE_LOCK_COMPARE_SWAP,
			   get_subaddr(dice, SND_DICE_ADDR_TYPE_GLOBAL,
				       GLOBAL_OWNER),
			   buffer, 2 * 8, FW_QUIET |
			   FW_FIXED_GENERATION | dice->owner_generation);

	kfree(buffer);

	dice->owner_generation = -1;
}

void snd_dice_transaction_destroy(struct snd_dice *dice)
{
	struct fw_address_handler *handler = &dice->notification_handler;

	if (handler->callback_data == NULL)
		return;

	unregister_notification_address(dice);

	fw_core_remove_address_handler(handler);
	handler->callback_data = NULL;
}

int snd_dice_transaction_reinit(struct snd_dice *dice)
{
	struct fw_address_handler *handler = &dice->notification_handler;

	if (handler->callback_data == NULL)
		return -EINVAL;

	return register_notification_address(dice, false);
}

static int get_subaddrs(struct snd_dice *dice)
{
	static const int min_values[10] = {
		10, 0x60 / 4,
		10, 0x18 / 4,
		10, 0x18 / 4,
		0, 0,
		0, 0,
	};
	__be32 *pointers;
	__be32 version;
	u32 data;
	unsigned int i;
	int err;

	pointers = kmalloc_array(ARRAY_SIZE(min_values), sizeof(__be32),
				 GFP_KERNEL);

Annotation

Implementation Notes