summaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2014-01-18 17:32:20 +0100
committerStefan Richter <stefanr@s5r6.in-berlin.de>2014-01-20 01:11:13 +0100
commitfcd46b34425da52703fe65b7f08850c509dcb0ed (patch)
treea133fd9d86111bbf3de37d882c00e8c3709eea8e /drivers/firewire
parent8bc588e0e585bc9085df75e84d4d5635f45cf360 (diff)
downloadlinux-stable-fcd46b34425da52703fe65b7f08850c509dcb0ed.tar.gz
linux-stable-fcd46b34425da52703fe65b7f08850c509dcb0ed.tar.bz2
linux-stable-fcd46b34425da52703fe65b7f08850c509dcb0ed.zip
firewire: Enable remote DMA above 4 GB
This makes all of a machine's memory accessible to remote debugging via FireWire, using the physical response unit (i.e. RDMA) of OHCI-1394 link layer controllers. This requires actual support by the controller. The only ones currently known to support it are Agere/LSI FW643. Most if not all other OHCI-1394 controllers do not implement the optional Physical Upper Bound register. With them, RDMA will continue to be limited to the lowermost 4 GB. firewire-ohci's startup message in the kernel log is augmented to tell whether the controller does expose more than 4 GB to RDMA. While OHCI-1394 allows for a maximum Physical Upper Bound of 0xffff'0000'0000 (near 256 TB), this implementation sets it to 0x8000'0000'0000 (128 TB) in order to avoid interference with applications that require interrupt-served asynchronous request reception at respectively low addresses. Note, this change does not switch remote DMA on. It only increases the range of remote access to all memory (instead of just 4 GB) whenever remote DMA was switched on by other means. The latter is achieved by setting firewire-ohci's remote_dma parameter, or if the physical DMA filter is opened through firewire-sbp2. Derived from patch "firewire: Enable physical DMA above 4GB" by Peter Hurley <peter@hurleysoftware.com> from March 27, 2013. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/core-transaction.c6
-rw-r--r--drivers/firewire/core.h3
-rw-r--r--drivers/firewire/ohci.c8
3 files changed, 11 insertions, 6 deletions
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c
index 0e799516a2ab..eb6935c8ad94 100644
--- a/drivers/firewire/core-transaction.c
+++ b/drivers/firewire/core-transaction.c
@@ -523,11 +523,11 @@ static DEFINE_SPINLOCK(address_handler_list_lock);
static LIST_HEAD(address_handler_list);
const struct fw_address_region fw_high_memory_region =
- { .start = 0x000100000000ULL, .end = 0xffffe0000000ULL, };
+ { .start = FW_MAX_PHYSICAL_RANGE, .end = 0xffffe0000000ULL, };
EXPORT_SYMBOL(fw_high_memory_region);
static const struct fw_address_region low_memory_region =
- { .start = 0x000000000000ULL, .end = 0x000100000000ULL, };
+ { .start = 0x000000000000ULL, .end = FW_MAX_PHYSICAL_RANGE, };
#if 0
const struct fw_address_region fw_private_region =
@@ -1217,7 +1217,7 @@ static void handle_low_memory(struct fw_card *card, struct fw_request *request,
}
static struct fw_address_handler low_memory = {
- .length = 0x000100000000ULL,
+ .length = FW_MAX_PHYSICAL_RANGE,
.address_callback = handle_low_memory,
};
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index 515a42c786d0..c98764aeeec6 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -237,6 +237,9 @@ static inline bool is_next_generation(int new_generation, int old_generation)
#define LOCAL_BUS 0xffc0
+/* arbitrarily chosen maximum range for physical DMA: 128 TB */
+#define FW_MAX_PHYSICAL_RANGE (128ULL << 40)
+
void fw_core_handle_request(struct fw_card *card, struct fw_packet *request);
void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);
int fw_get_response_length(struct fw_request *request);
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 036fb3bd5659..6f74d8d3f700 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -2367,7 +2367,7 @@ static int ohci_enable(struct fw_card *card,
reg_write(ohci, OHCI1394_FairnessControl, 0);
card->priority_budget_implemented = ohci->pri_req_max != 0;
- reg_write(ohci, OHCI1394_PhyUpperBound, 0x00010000);
+ reg_write(ohci, OHCI1394_PhyUpperBound, FW_MAX_PHYSICAL_RANGE >> 16);
reg_write(ohci, OHCI1394_IntEventClear, ~0);
reg_write(ohci, OHCI1394_IntMaskClear, ~0);
@@ -3723,9 +3723,11 @@ static int pci_probe(struct pci_dev *dev,
version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
ohci_notice(ohci,
"added OHCI v%x.%x device as card %d, "
- "%d IR + %d IT contexts, quirks 0x%x\n",
+ "%d IR + %d IT contexts, quirks 0x%x%s\n",
version >> 16, version & 0xff, ohci->card.index,
- ohci->n_ir, ohci->n_it, ohci->quirks);
+ ohci->n_ir, ohci->n_it, ohci->quirks,
+ reg_read(ohci, OHCI1394_PhyUpperBound) ?
+ ", >4 GB phys DMA" : "");
return 0;