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

Commit 441c196e 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: document the sysfs ABIs
  firewire: cdev: ABI documentation enhancements
  firewire: cdev: prevent race between first get_info ioctl and bus reset event queuing
  firewire: cdev: return -ENOTTY for unimplemented ioctls, not -EINVAL
  firewire: ohci: skip soft reset retries after card ejection
  firewire: ohci: fix PHY reg access after card ejection
  firewire: ohci: add a comment on PHY reg access serialization
  firewire: ohci: reduce potential context_stop latency
  firewire: ohci: remove superfluous posted write flushes
  firewire: net: replacing deprecated __attribute__((packed)) with __packed
parents 951cc93a 9a00c24a
Loading
Loading
Loading
Loading
+103 −0
Original line number Original line Diff line number Diff line
What:		/dev/fw[0-9]+
Date:		May 2007
KernelVersion:	2.6.22
Contact:	linux1394-devel@lists.sourceforge.net
Description:
		The character device files /dev/fw* are the interface between
		firewire-core and IEEE 1394 device drivers implemented in
		userspace.  The ioctl(2)- and read(2)-based ABI is defined and
		documented in <linux/firewire-cdev.h>.

		This ABI offers most of the features which firewire-core also
		exposes to kernelspace IEEE 1394 drivers.

		Each /dev/fw* is associated with one IEEE 1394 node, which can
		be remote or local nodes.  Operations on a /dev/fw* file have
		different scope:
		  - The 1394 node which is associated with the file:
			  - Asynchronous request transmission
			  - Get the Configuration ROM
			  - Query node ID
			  - Query maximum speed of the path between this node
			    and local node
		  - The 1394 bus (i.e. "card") to which the node is attached to:
			  - Isochronous stream transmission and reception
			  - Asynchronous stream transmission and reception
			  - Asynchronous broadcast request transmission
			  - PHY packet transmission and reception
			  - Allocate, reallocate, deallocate isochronous
			    resources (channels, bandwidth) at the bus's IRM
			  - Query node IDs of local node, root node, IRM, bus
			    manager
			  - Query cycle time
			  - Bus reset initiation, bus reset event reception
		  - All 1394 buses:
			  - Allocation of IEEE 1212 address ranges on the local
			    link layers, reception of inbound requests to such
			    an address range, asynchronous response transmission
			    to inbound requests
			  - Addition of descriptors or directories to the local
			    nodes' Configuration ROM

		Due to the different scope of operations and in order to let
		userland implement different access permission models, some
		operations are restricted to /dev/fw* files that are associated
		with a local node:
			  - Addition of descriptors or directories to the local
			    nodes' Configuration ROM
			  - PHY packet transmission and reception

		A /dev/fw* file remains associated with one particular node
		during its entire life time.  Bus topology changes, and hence
		node ID changes, are tracked by firewire-core.  ABI users do not
		need to be aware of topology.

		The following file operations are supported:

		open(2)
		Currently the only useful flags are O_RDWR.

		ioctl(2)
		Initiate various actions.  Some take immediate effect, others
		are performed asynchronously while or after the ioctl returns.
		See the inline documentation in <linux/firewire-cdev.h> for
		descriptions of all ioctls.

		poll(2), select(2), epoll_wait(2) etc.
		Watch for events to become available to be read.

		read(2)
		Receive various events.  There are solicited events like
		outbound asynchronous transaction completion or isochronous
		buffer completion, and unsolicited events such as bus resets,
		request reception, or PHY packet reception.  Always use a read
		buffer which is large enough to receive the largest event that
		could ever arrive.  See <linux/firewire-cdev.h> for descriptions
		of all event types and for which ioctls affect reception of
		events.

		mmap(2)
		Allocate a DMA buffer for isochronous reception or transmission
		and map it into the process address space.  The arguments should
		be used as follows:  addr = NULL, length = the desired buffer
		size, i.e. number of packets times size of largest packet,
		prot = at least PROT_READ for reception and at least PROT_WRITE
		for transmission, flags = MAP_SHARED, fd = the handle to the
		/dev/fw*, offset = 0.

		Isochronous reception works in packet-per-buffer fashion except
		for multichannel reception which works in buffer-fill mode.

		munmap(2)
		Unmap the isochronous I/O buffer from the process address space.

		close(2)
		Besides stopping and freeing I/O contexts that were associated
		with the file descriptor, back out any changes to the local
		nodes' Configuration ROM.  Deallocate isochronous channels and
		bandwidth at the IRM that were marked for kernel-assisted
		re- and deallocation.

Users:		libraw1394
		libdc1394
		tools like jujuutils, fwhack, ...
+122 −0
Original line number Original line Diff line number Diff line
What:		/sys/bus/firewire/devices/fw[0-9]+/
Date:		May 2007
KernelVersion:	2.6.22
Contact:	linux1394-devel@lists.sourceforge.net
Description:
		IEEE 1394 node device attributes.
		Read-only.  Mutable during the node device's lifetime.
		See IEEE 1212 for semantic definitions.

		config_rom
			Contents of the Configuration ROM register.
			Binary attribute; an array of host-endian u32.

		guid
			The node's EUI-64 in the bus information block of
			Configuration ROM.
			Hexadecimal string representation of an u64.


What:		/sys/bus/firewire/devices/fw[0-9]+/units
Date:		June 2009
KernelVersion:	2.6.31
Contact:	linux1394-devel@lists.sourceforge.net
Description:
		IEEE 1394 node device attribute.
		Read-only.  Mutable during the node device's lifetime.
		See IEEE 1212 for semantic definitions.

		units
			Summary of all units present in an IEEE 1394 node.
			Contains space-separated tuples of specifier_id and
			version of each unit present in the node.  Specifier_id
			and version are hexadecimal string representations of
			u24 of the respective unit directory entries.
			Specifier_id and version within each tuple are separated
			by a colon.

Users:		udev rules to set ownership and access permissions or ACLs of
		/dev/fw[0-9]+ character device files


What:		/sys/bus/firewire/devices/fw[0-9]+[.][0-9]+/
Date:		May 2007
KernelVersion:	2.6.22
Contact:	linux1394-devel@lists.sourceforge.net
Description:
		IEEE 1394 unit device attributes.
		Read-only.  Immutable during the unit device's lifetime.
		See IEEE 1212 for semantic definitions.

		modalias
			Same as MODALIAS in the uevent at device creation.

		rom_index
			Offset of the unit directory within the parent device's
			(node device's) Configuration ROM, in quadlets.
			Decimal string representation.


What:		/sys/bus/firewire/devices/*/
Date:		May 2007
KernelVersion:	2.6.22
Contact:	linux1394-devel@lists.sourceforge.net
Description:
		Attributes common to IEEE 1394 node devices and unit devices.
		Read-only.  Mutable during the node device's lifetime.
		Immutable during the unit device's lifetime.
		See IEEE 1212 for semantic definitions.

		These attributes are only created if the root directory of an
		IEEE 1394 node or the unit directory of an IEEE 1394 unit
		actually contains according entries.

		hardware_version
			Hexadecimal string representation of an u24.

		hardware_version_name
			Contents of a respective textual descriptor leaf.

		model
			Hexadecimal string representation of an u24.

		model_name
			Contents of a respective textual descriptor leaf.

		specifier_id
			Hexadecimal string representation of an u24.
			Mandatory in unit directories according to IEEE 1212.

		vendor
			Hexadecimal string representation of an u24.
			Mandatory in the root directory according to IEEE 1212.

		vendor_name
			Contents of a respective textual descriptor leaf.

		version
			Hexadecimal string representation of an u24.
			Mandatory in unit directories according to IEEE 1212.


What:		/sys/bus/firewire/drivers/sbp2/fw*/host*/target*/*:*:*:*/ieee1394_id
		formerly
		/sys/bus/ieee1394/drivers/sbp2/fw*/host*/target*/*:*:*:*/ieee1394_id
Date:		Feb 2004
KernelVersion:	2.6.4
Contact:	linux1394-devel@lists.sourceforge.net
Description:
		SCSI target port identifier and logical unit identifier of a
		logical unit of an SBP-2 target.  The identifiers are specified
		in SAM-2...SAM-4 annex A.  They are persistent and world-wide
		unique properties the SBP-2 attached target.

		Read-only attribute, immutable during the target's lifetime.
		Format, as exposed by firewire-sbp2 since 2.6.22, May 2007:
		Colon-separated hexadecimal string representations of
			u64 EUI-64 : u24 directory_ID : u16 LUN
		without 0x prefixes, without whitespace.  The former sbp2 driver
		(removed in 2.6.37 after being superseded by firewire-sbp2) used
		a somewhat shorter format which was not as close to SAM.

Users:		udev rules to create /dev/disk/by-id/ symlinks
+11 −9
Original line number Original line Diff line number Diff line
@@ -253,14 +253,11 @@ static int fw_device_op_open(struct inode *inode, struct file *file)
	init_waitqueue_head(&client->wait);
	init_waitqueue_head(&client->wait);
	init_waitqueue_head(&client->tx_flush_wait);
	init_waitqueue_head(&client->tx_flush_wait);
	INIT_LIST_HEAD(&client->phy_receiver_link);
	INIT_LIST_HEAD(&client->phy_receiver_link);
	INIT_LIST_HEAD(&client->link);
	kref_init(&client->kref);
	kref_init(&client->kref);


	file->private_data = client;
	file->private_data = client;


	mutex_lock(&device->client_list_mutex);
	list_add_tail(&client->link, &device->client_list);
	mutex_unlock(&device->client_list_mutex);

	return nonseekable_open(inode, file);
	return nonseekable_open(inode, file);
}
}


@@ -451,15 +448,20 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg)
	if (ret != 0)
	if (ret != 0)
		return -EFAULT;
		return -EFAULT;


	mutex_lock(&client->device->client_list_mutex);

	client->bus_reset_closure = a->bus_reset_closure;
	client->bus_reset_closure = a->bus_reset_closure;
	if (a->bus_reset != 0) {
	if (a->bus_reset != 0) {
		fill_bus_reset_event(&bus_reset, client);
		fill_bus_reset_event(&bus_reset, client);
		if (copy_to_user(u64_to_uptr(a->bus_reset),
		ret = copy_to_user(u64_to_uptr(a->bus_reset),
				 &bus_reset, sizeof(bus_reset)))
				   &bus_reset, sizeof(bus_reset));
			return -EFAULT;
	}
	}
	if (ret == 0 && list_empty(&client->link))
		list_add_tail(&client->link, &client->device->client_list);


	return 0;
	mutex_unlock(&client->device->client_list_mutex);

	return ret ? -EFAULT : 0;
}
}


static int add_client_resource(struct client *client,
static int add_client_resource(struct client *client,
@@ -1583,7 +1585,7 @@ static int dispatch_ioctl(struct client *client,
	if (_IOC_TYPE(cmd) != '#' ||
	if (_IOC_TYPE(cmd) != '#' ||
	    _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers) ||
	    _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers) ||
	    _IOC_SIZE(cmd) > sizeof(buffer))
	    _IOC_SIZE(cmd) > sizeof(buffer))
		return -EINVAL;
		return -ENOTTY;


	if (_IOC_DIR(cmd) == _IOC_READ)
	if (_IOC_DIR(cmd) == _IOC_READ)
		memset(&buffer, 0, _IOC_SIZE(cmd));
		memset(&buffer, 0, _IOC_SIZE(cmd));
+3 −2
Original line number Original line Diff line number Diff line
@@ -7,6 +7,7 @@
 */
 */


#include <linux/bug.h>
#include <linux/bug.h>
#include <linux/compiler.h>
#include <linux/delay.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/device.h>
#include <linux/ethtool.h>
#include <linux/ethtool.h>
@@ -73,7 +74,7 @@ struct rfc2734_arp {
	__be32 fifo_lo;		/* lo 32bits of sender's FIFO addr	*/
	__be32 fifo_lo;		/* lo 32bits of sender's FIFO addr	*/
	__be32 sip;		/* Sender's IP Address			*/
	__be32 sip;		/* Sender's IP Address			*/
	__be32 tip;		/* IP Address of requested hw addr	*/
	__be32 tip;		/* IP Address of requested hw addr	*/
} __attribute__((packed));
} __packed;


/* This header format is specific to this driver implementation. */
/* This header format is specific to this driver implementation. */
#define FWNET_ALEN	8
#define FWNET_ALEN	8
@@ -81,7 +82,7 @@ struct rfc2734_arp {
struct fwnet_header {
struct fwnet_header {
	u8 h_dest[FWNET_ALEN];	/* destination address */
	u8 h_dest[FWNET_ALEN];	/* destination address */
	__be16 h_proto;		/* packet type ID field */
	__be16 h_proto;		/* packet type ID field */
} __attribute__((packed));
} __packed;


/* IPv4 and IPv6 encapsulation header */
/* IPv4 and IPv6 encapsulation header */
struct rfc2734_header {
struct rfc2734_header {
+27 −15
Original line number Original line Diff line number Diff line
@@ -253,7 +253,6 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
#define OHCI1394_MAX_PHYS_RESP_RETRIES	0x8
#define OHCI1394_MAX_PHYS_RESP_RETRIES	0x8


#define OHCI1394_REGISTER_SIZE		0x800
#define OHCI1394_REGISTER_SIZE		0x800
#define OHCI_LOOP_COUNT			500
#define OHCI1394_PCI_HCI_Control	0x40
#define OHCI1394_PCI_HCI_Control	0x40
#define SELF_ID_BUF_SIZE		0x800
#define SELF_ID_BUF_SIZE		0x800
#define OHCI_TCODE_PHY_PACKET		0x0e
#define OHCI_TCODE_PHY_PACKET		0x0e
@@ -514,6 +513,12 @@ static inline void flush_writes(const struct fw_ohci *ohci)
	reg_read(ohci, OHCI1394_Version);
	reg_read(ohci, OHCI1394_Version);
}
}


/*
 * Beware!  read_phy_reg(), write_phy_reg(), update_phy_reg(), and
 * read_paged_phy_reg() require the caller to hold ohci->phy_reg_mutex.
 * In other words, only use ohci_read_phy_reg() and ohci_update_phy_reg()
 * directly.  Exceptions are intrinsically serialized contexts like pci_probe.
 */
static int read_phy_reg(struct fw_ohci *ohci, int addr)
static int read_phy_reg(struct fw_ohci *ohci, int addr)
{
{
	u32 val;
	u32 val;
@@ -522,6 +527,9 @@ static int read_phy_reg(struct fw_ohci *ohci, int addr)
	reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr));
	reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr));
	for (i = 0; i < 3 + 100; i++) {
	for (i = 0; i < 3 + 100; i++) {
		val = reg_read(ohci, OHCI1394_PhyControl);
		val = reg_read(ohci, OHCI1394_PhyControl);
		if (!~val)
			return -ENODEV; /* Card was ejected. */

		if (val & OHCI1394_PhyControl_ReadDone)
		if (val & OHCI1394_PhyControl_ReadDone)
			return OHCI1394_PhyControl_ReadData(val);
			return OHCI1394_PhyControl_ReadData(val);


@@ -545,6 +553,9 @@ static int write_phy_reg(const struct fw_ohci *ohci, int addr, u32 val)
		  OHCI1394_PhyControl_Write(addr, val));
		  OHCI1394_PhyControl_Write(addr, val));
	for (i = 0; i < 3 + 100; i++) {
	for (i = 0; i < 3 + 100; i++) {
		val = reg_read(ohci, OHCI1394_PhyControl);
		val = reg_read(ohci, OHCI1394_PhyControl);
		if (!~val)
			return -ENODEV; /* Card was ejected. */

		if (!(val & OHCI1394_PhyControl_WritePending))
		if (!(val & OHCI1394_PhyControl_WritePending))
			return 0;
			return 0;


@@ -630,7 +641,6 @@ static void ar_context_link_page(struct ar_context *ctx, unsigned int index)
	ctx->last_buffer_index = index;
	ctx->last_buffer_index = index;


	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
	flush_writes(ctx->ohci);
}
}


static void ar_context_release(struct ar_context *ctx)
static void ar_context_release(struct ar_context *ctx)
@@ -1002,7 +1012,6 @@ static void ar_context_run(struct ar_context *ctx)


	reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ctx->descriptors_bus | 1);
	reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ctx->descriptors_bus | 1);
	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN);
	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN);
	flush_writes(ctx->ohci);
}
}


static struct descriptor *find_branch_descriptor(struct descriptor *d, int z)
static struct descriptor *find_branch_descriptor(struct descriptor *d, int z)
@@ -1202,14 +1211,14 @@ static void context_stop(struct context *ctx)


	reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN);
	reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN);
	ctx->running = false;
	ctx->running = false;
	flush_writes(ctx->ohci);


	for (i = 0; i < 10; i++) {
	for (i = 0; i < 1000; i++) {
		reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs));
		reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs));
		if ((reg & CONTEXT_ACTIVE) == 0)
		if ((reg & CONTEXT_ACTIVE) == 0)
			return;
			return;


		mdelay(1);
		if (i)
			udelay(10);
	}
	}
	fw_error("Error: DMA context still active (0x%08x)\n", reg);
	fw_error("Error: DMA context still active (0x%08x)\n", reg);
}
}
@@ -1346,12 +1355,10 @@ static int at_context_queue_packet(struct context *ctx,


	context_append(ctx, d, z, 4 - z);
	context_append(ctx, d, z, 4 - z);


	if (ctx->running) {
	if (ctx->running)
		reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
		reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
		flush_writes(ohci);
	else
	} else {
		context_run(ctx, 0);
		context_run(ctx, 0);
	}


	return 0;
	return 0;
}
}
@@ -1960,14 +1967,18 @@ static irqreturn_t irq_handler(int irq, void *data)


static int software_reset(struct fw_ohci *ohci)
static int software_reset(struct fw_ohci *ohci)
{
{
	u32 val;
	int i;
	int i;


	reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
	reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
	for (i = 0; i < 500; i++) {
		val = reg_read(ohci, OHCI1394_HCControlSet);
		if (!~val)
			return -ENODEV; /* Card was ejected. */


	for (i = 0; i < OHCI_LOOP_COUNT; i++) {
		if (!(val & OHCI1394_HCControl_softReset))
		if ((reg_read(ohci, OHCI1394_HCControlSet) &
		     OHCI1394_HCControl_softReset) == 0)
			return 0;
			return 0;

		msleep(1);
		msleep(1);
	}
	}


@@ -2197,7 +2208,9 @@ static int ohci_enable(struct fw_card *card,
		  OHCI1394_LinkControl_rcvPhyPkt);
		  OHCI1394_LinkControl_rcvPhyPkt);


	ar_context_run(&ohci->ar_request_ctx);
	ar_context_run(&ohci->ar_request_ctx);
	ar_context_run(&ohci->ar_response_ctx); /* also flushes writes */
	ar_context_run(&ohci->ar_response_ctx);

	flush_writes(ohci);


	/* We are ready to go, reset bus to finish initialization. */
	/* We are ready to go, reset bus to finish initialization. */
	fw_schedule_bus_reset(&ohci->card, false, true);
	fw_schedule_bus_reset(&ohci->card, false, true);
@@ -3129,7 +3142,6 @@ static void ohci_flush_queue_iso(struct fw_iso_context *base)
			&container_of(base, struct iso_context, base)->context;
			&container_of(base, struct iso_context, base)->context;


	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
	flush_writes(ctx->ohci);
}
}


static const struct fw_card_driver ohci_driver = {
static const struct fw_card_driver ohci_driver = {
Loading