aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/stable/sysfs-bus-firewire11
-rw-r--r--drivers/firewire/core-device.c9
-rw-r--r--drivers/firewire/core-iso.c2
-rw-r--r--drivers/firewire/core-transaction.c23
-rw-r--r--drivers/firewire/ohci.c30
-rw-r--r--include/linux/firewire.h4
6 files changed, 68 insertions, 11 deletions
diff --git a/Documentation/ABI/stable/sysfs-bus-firewire b/Documentation/ABI/stable/sysfs-bus-firewire
index 3d484e5dc84..41e5a0cd1e3 100644
--- a/Documentation/ABI/stable/sysfs-bus-firewire
+++ b/Documentation/ABI/stable/sysfs-bus-firewire
@@ -39,6 +39,17 @@ 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]+/is_local
+Date: July 2012
+KernelVersion: 3.6
+Contact: linux1394-devel@lists.sourceforge.net
+Description:
+ IEEE 1394 node device attribute.
+ Read-only and immutable.
+Values: 1: The sysfs entry represents a local node (a controller card).
+ 0: The sysfs entry represents a remote node.
+
+
What: /sys/bus/firewire/devices/fw[0-9]+[.][0-9]+/
Date: May 2007
KernelVersion: 2.6.22
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c
index 4d460ef8716..7a05fd24d68 100644
--- a/drivers/firewire/core-device.c
+++ b/drivers/firewire/core-device.c
@@ -398,6 +398,14 @@ static ssize_t guid_show(struct device *dev,
return ret;
}
+static ssize_t is_local_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fw_device *device = fw_device(dev);
+
+ return sprintf(buf, "%u\n", device->is_local);
+}
+
static int units_sprintf(char *buf, const u32 *directory)
{
struct fw_csr_iterator ci;
@@ -447,6 +455,7 @@ static ssize_t units_show(struct device *dev,
static struct device_attribute fw_device_attributes[] = {
__ATTR_RO(config_rom),
__ATTR_RO(guid),
+ __ATTR_RO(is_local),
__ATTR_RO(units),
__ATTR_NULL,
};
diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c
index 8382e27e9a2..38c0aa60b2c 100644
--- a/drivers/firewire/core-iso.c
+++ b/drivers/firewire/core-iso.c
@@ -146,7 +146,7 @@ EXPORT_SYMBOL(fw_iso_buffer_destroy);
/* Convert DMA address to offset into virtually contiguous buffer. */
size_t fw_iso_buffer_lookup(struct fw_iso_buffer *buffer, dma_addr_t completed)
{
- int i;
+ size_t i;
dma_addr_t address;
ssize_t offset;
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c
index 780708dc6e2..87d6f2d2f02 100644
--- a/drivers/firewire/core-transaction.c
+++ b/drivers/firewire/core-transaction.c
@@ -525,9 +525,10 @@ const struct fw_address_region fw_high_memory_region =
{ .start = 0x000100000000ULL, .end = 0xffffe0000000ULL, };
EXPORT_SYMBOL(fw_high_memory_region);
-#if 0
-const struct fw_address_region fw_low_memory_region =
+static const struct fw_address_region low_memory_region =
{ .start = 0x000000000000ULL, .end = 0x000100000000ULL, };
+
+#if 0
const struct fw_address_region fw_private_region =
{ .start = 0xffffe0000000ULL, .end = 0xfffff0000000ULL, };
const struct fw_address_region fw_csr_region =
@@ -1198,6 +1199,23 @@ static struct fw_address_handler registers = {
.address_callback = handle_registers,
};
+static void handle_low_memory(struct fw_card *card, struct fw_request *request,
+ int tcode, int destination, int source, int generation,
+ unsigned long long offset, void *payload, size_t length,
+ void *callback_data)
+{
+ /*
+ * This catches requests not handled by the physical DMA unit,
+ * i.e., wrong transaction types or unauthorized source nodes.
+ */
+ fw_send_response(card, request, RCODE_TYPE_ERROR);
+}
+
+static struct fw_address_handler low_memory = {
+ .length = 0x000100000000ULL,
+ .address_callback = handle_low_memory,
+};
+
MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
MODULE_DESCRIPTION("Core IEEE1394 transaction logic");
MODULE_LICENSE("GPL");
@@ -1259,6 +1277,7 @@ static int __init fw_core_init(void)
fw_core_add_address_handler(&topology_map, &topology_map_region);
fw_core_add_address_handler(&registers, &registers_region);
+ fw_core_add_address_handler(&low_memory, &low_memory_region);
fw_core_add_descriptor(&vendor_id_descriptor);
fw_core_add_descriptor(&model_id_descriptor);
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index c1af05e834b..c788dbdaf3b 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -191,6 +191,7 @@ struct fw_ohci {
unsigned quirks;
unsigned int pri_req_max;
u32 bus_time;
+ bool bus_time_running;
bool is_root;
bool csr_state_setclear_abdicate;
int n_ir;
@@ -1726,6 +1727,13 @@ static u32 update_bus_time(struct fw_ohci *ohci)
{
u32 cycle_time_seconds = get_cycle_time(ohci) >> 25;
+ if (unlikely(!ohci->bus_time_running)) {
+ reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_cycle64Seconds);
+ ohci->bus_time = (lower_32_bits(get_seconds()) & ~0x7f) |
+ (cycle_time_seconds & 0x40);
+ ohci->bus_time_running = true;
+ }
+
if ((ohci->bus_time & 0x40) != (cycle_time_seconds & 0x40))
ohci->bus_time += 0x40;
@@ -2213,7 +2221,7 @@ static int ohci_enable(struct fw_card *card,
{
struct fw_ohci *ohci = fw_ohci(card);
struct pci_dev *dev = to_pci_dev(card->device);
- u32 lps, seconds, version, irqs;
+ u32 lps, version, irqs;
int i, ret;
if (software_reset(ohci)) {
@@ -2269,9 +2277,12 @@ static int ohci_enable(struct fw_card *card,
(OHCI1394_MAX_PHYS_RESP_RETRIES << 8) |
(200 << 16));
- seconds = lower_32_bits(get_seconds());
- reg_write(ohci, OHCI1394_IsochronousCycleTimer, seconds << 25);
- ohci->bus_time = seconds & ~0x3f;
+ ohci->bus_time_running = false;
+
+ for (i = 0; i < 32; i++)
+ if (ohci->ir_context_support & (1 << i))
+ reg_write(ohci, OHCI1394_IsoRcvContextControlClear(i),
+ IR_CONTEXT_MULTI_CHANNEL_MODE);
version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
if (version >= OHCI_VERSION_1_1) {
@@ -2369,7 +2380,6 @@ static int ohci_enable(struct fw_card *card,
OHCI1394_postedWriteErr |
OHCI1394_selfIDComplete |
OHCI1394_regAccessFail |
- OHCI1394_cycle64Seconds |
OHCI1394_cycleInconsistent |
OHCI1394_unrecoverableError |
OHCI1394_cycleTooLong |
@@ -2658,7 +2668,8 @@ static void ohci_write_csr(struct fw_card *card, int csr_offset, u32 value)
case CSR_BUS_TIME:
spin_lock_irqsave(&ohci->lock, flags);
- ohci->bus_time = (ohci->bus_time & 0x7f) | (value & ~0x7f);
+ ohci->bus_time = (update_bus_time(ohci) & 0x40) |
+ (value & ~0x7f);
spin_unlock_irqrestore(&ohci->lock, flags);
break;
@@ -3539,6 +3550,13 @@ static int __devinit pci_probe(struct pci_dev *dev,
INIT_WORK(&ohci->bus_reset_work, bus_reset_work);
+ if (!(pci_resource_flags(dev, 0) & IORESOURCE_MEM) ||
+ pci_resource_len(dev, 0) < OHCI1394_REGISTER_SIZE) {
+ dev_err(&dev->dev, "invalid MMIO resource\n");
+ err = -ENXIO;
+ goto fail_disable;
+ }
+
err = pci_request_region(dev, 0, ohci_driver_name);
if (err) {
dev_err(&dev->dev, "MMIO resource unavailable\n");
diff --git a/include/linux/firewire.h b/include/linux/firewire.h
index 7edcf103171..db04ec5121c 100644
--- a/include/linux/firewire.h
+++ b/include/linux/firewire.h
@@ -152,7 +152,7 @@ static inline void fw_card_put(struct fw_card *card)
struct fw_attribute_group {
struct attribute_group *groups[2];
struct attribute_group group;
- struct attribute *attrs[12];
+ struct attribute *attrs[13];
};
enum fw_device_state {
@@ -321,7 +321,7 @@ struct fw_transaction {
struct fw_address_handler {
u64 offset;
- size_t length;
+ u64 length;
fw_address_callback_t address_callback;
void *callback_data;
struct list_head link;