From 1e119fa9950dfe0e6d97470098db776110ca47a9 Mon Sep 17 00:00:00 2001 From: Jay Fenlason Date: Sun, 20 Jul 2008 14:20:53 +0200 Subject: firewire: fw_send_request_sync() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Share code between fw_send_request + wait_for_completion callers. Signed-off-by: Jay Fenlason Addendum: Removes an unnecessary struct and an ununsed retry loop. Calls it fw_run_transaction() instead of fw_send_request_sync(). Signed-off-by: Stefan Richter Acked-by: Kristian Høgsberg --- drivers/firewire/fw-sbp2.c | 46 ++++++++++++---------------------------------- 1 file changed, 12 insertions(+), 34 deletions(-) (limited to 'drivers/firewire/fw-sbp2.c') diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index aaff50ebba1..05997cee4f3 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -621,25 +621,15 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, return retval; } -static void -complete_agent_reset_write(struct fw_card *card, int rcode, - void *payload, size_t length, void *done) -{ - complete(done); -} - static void sbp2_agent_reset(struct sbp2_logical_unit *lu) { struct fw_device *device = fw_device(lu->tgt->unit->device.parent); - DECLARE_COMPLETION_ONSTACK(done); - struct fw_transaction t; - static u32 z; + __be32 d = 0; - fw_send_request(device->card, &t, TCODE_WRITE_QUADLET_REQUEST, - lu->tgt->node_id, lu->generation, device->max_speed, - lu->command_block_agent_address + SBP2_AGENT_RESET, - &z, sizeof(z), complete_agent_reset_write, &done); - wait_for_completion(&done); + fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST, + lu->tgt->node_id, lu->generation, device->max_speed, + lu->command_block_agent_address + SBP2_AGENT_RESET, + &d, sizeof(d)); } static void @@ -653,7 +643,7 @@ static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu) { struct fw_device *device = fw_device(lu->tgt->unit->device.parent); struct fw_transaction *t; - static u32 z; + static __be32 d; t = kmalloc(sizeof(*t), GFP_ATOMIC); if (t == NULL) @@ -662,7 +652,7 @@ static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu) fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST, lu->tgt->node_id, lu->generation, device->max_speed, lu->command_block_agent_address + SBP2_AGENT_RESET, - &z, sizeof(z), complete_agent_reset_write_no_wait, t); + &d, sizeof(d), complete_agent_reset_write_no_wait, t); } static void sbp2_set_generation(struct sbp2_logical_unit *lu, int generation) @@ -823,13 +813,6 @@ static void sbp2_target_put(struct sbp2_target *tgt) kref_put(&tgt->kref, sbp2_release_target); } -static void -complete_set_busy_timeout(struct fw_card *card, int rcode, - void *payload, size_t length, void *done) -{ - complete(done); -} - /* * Write retransmit retry values into the BUSY_TIMEOUT register. * - The single-phase retry protocol is supported by all SBP-2 devices, but the @@ -849,17 +832,12 @@ complete_set_busy_timeout(struct fw_card *card, int rcode, static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu) { struct fw_device *device = fw_device(lu->tgt->unit->device.parent); - DECLARE_COMPLETION_ONSTACK(done); - struct fw_transaction t; - static __be32 busy_timeout; - - busy_timeout = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT); + __be32 d = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT); - fw_send_request(device->card, &t, TCODE_WRITE_QUADLET_REQUEST, - lu->tgt->node_id, lu->generation, device->max_speed, - CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT, &busy_timeout, - sizeof(busy_timeout), complete_set_busy_timeout, &done); - wait_for_completion(&done); + fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST, + lu->tgt->node_id, lu->generation, device->max_speed, + CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT, + &d, sizeof(d)); } static void sbp2_reconnect(struct work_struct *work); -- cgit v1.2.3-70-g09d2 From 09b12dd4e3caff165a0f17a2f3ebd2bbc8544cc6 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Thu, 14 Aug 2008 21:47:21 +0200 Subject: firewire: fw-sbp2: enforce s/g segment size limit 1. We don't need to round the SBP-2 segment size limit down to a multiple of 4 kB (0xffff -> 0xf000). It is only necessary to ensure quadlet alignment (0xffff -> 0xfffc). 2. Use dma_set_max_seg_size() to tell the DMA mapping infrastructure and the block IO layer about the restriction. This way we can remove the size checks and segment splitting in the queuecommand path. This assumes that no other code in the firewire stack uses dma_map_sg() with conflicting requirements. It furthermore assumes that the controller device's platform actually allows us to set the segment size to our liking. Assert the latter with a BUG_ON(). 3. Also use blk_queue_max_segment_size() to tell the block IO layer about it. It cannot know it because our scsi_add_host() does not point to the FireWire controller's device. Thanks to Grant Grundler and FUJITA Tomonori for advice. Signed-off-by: Stefan Richter --- drivers/firewire/fw-sbp2.c | 63 ++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 36 deletions(-) (limited to 'drivers/firewire/fw-sbp2.c') diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index 05997cee4f3..5d8411afced 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -29,6 +29,7 @@ */ #include +#include #include #include #include @@ -181,10 +182,16 @@ struct sbp2_target { #define SBP2_MAX_LOGIN_ORB_TIMEOUT 40000U /* Timeout in ms */ #define SBP2_ORB_TIMEOUT 2000U /* Timeout in ms */ #define SBP2_ORB_NULL 0x80000000 -#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000 #define SBP2_RETRY_LIMIT 0xf /* 15 retries */ #define SBP2_CYCLE_LIMIT (0xc8 << 12) /* 200 125us cycles */ +/* + * The default maximum s/g segment size of a FireWire controller is + * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to + * be quadlet-aligned, we set the length limit to 0xffff & ~3. + */ +#define SBP2_MAX_SEG_SIZE 0xfffc + /* Unit directory keys */ #define SBP2_CSR_UNIT_CHARACTERISTICS 0x3a #define SBP2_CSR_FIRMWARE_REVISION 0x3c @@ -1099,6 +1106,10 @@ static int sbp2_probe(struct device *dev) struct Scsi_Host *shost; u32 model, firmware_revision; + if (dma_get_max_seg_size(device->card->device) > SBP2_MAX_SEG_SIZE) + BUG_ON(dma_set_max_seg_size(device->card->device, + SBP2_MAX_SEG_SIZE)); + shost = scsi_host_alloc(&scsi_driver_template, sizeof(*tgt)); if (shost == NULL) return -ENOMEM; @@ -1347,14 +1358,12 @@ static int sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device, struct sbp2_logical_unit *lu) { - struct scatterlist *sg; - int sg_len, l, i, j, count; - dma_addr_t sg_addr; - - sg = scsi_sglist(orb->cmd); - count = dma_map_sg(device->card->device, sg, scsi_sg_count(orb->cmd), - orb->cmd->sc_data_direction); - if (count == 0) + struct scatterlist *sg = scsi_sglist(orb->cmd); + int i, n; + + n = dma_map_sg(device->card->device, sg, scsi_sg_count(orb->cmd), + orb->cmd->sc_data_direction); + if (n == 0) goto fail; /* @@ -1364,7 +1373,7 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device, * as the second generation iPod which doesn't support page * tables. */ - if (count == 1 && sg_dma_len(sg) < SBP2_MAX_SG_ELEMENT_LENGTH) { + if (n == 1) { orb->request.data_descriptor.high = cpu_to_be32(lu->tgt->address_high); orb->request.data_descriptor.low = @@ -1374,29 +1383,9 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device, return 0; } - /* - * Convert the scatterlist to an sbp2 page table. If any - * scatterlist entries are too big for sbp2, we split them as we - * go. Even if we ask the block I/O layer to not give us sg - * elements larger than 65535 bytes, some IOMMUs may merge sg elements - * during DMA mapping, and Linux currently doesn't prevent this. - */ - for (i = 0, j = 0; i < count; i++, sg = sg_next(sg)) { - sg_len = sg_dma_len(sg); - sg_addr = sg_dma_address(sg); - while (sg_len) { - /* FIXME: This won't get us out of the pinch. */ - if (unlikely(j >= ARRAY_SIZE(orb->page_table))) { - fw_error("page table overflow\n"); - goto fail_page_table; - } - l = min(sg_len, SBP2_MAX_SG_ELEMENT_LENGTH); - orb->page_table[j].low = cpu_to_be32(sg_addr); - orb->page_table[j].high = cpu_to_be32(l << 16); - sg_addr += l; - sg_len -= l; - j++; - } + for_each_sg(sg, sg, n, i) { + orb->page_table[i].high = cpu_to_be32(sg_dma_len(sg) << 16); + orb->page_table[i].low = cpu_to_be32(sg_dma_address(sg)); } orb->page_table_bus = @@ -1415,13 +1404,13 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device, orb->request.data_descriptor.high = cpu_to_be32(lu->tgt->address_high); orb->request.data_descriptor.low = cpu_to_be32(orb->page_table_bus); orb->request.misc |= cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT | - COMMAND_ORB_DATA_SIZE(j)); + COMMAND_ORB_DATA_SIZE(n)); return 0; fail_page_table: - dma_unmap_sg(device->card->device, sg, scsi_sg_count(orb->cmd), - orb->cmd->sc_data_direction); + dma_unmap_sg(device->card->device, scsi_sglist(orb->cmd), + scsi_sg_count(orb->cmd), orb->cmd->sc_data_direction); fail: return -ENOMEM; } @@ -1542,6 +1531,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev) if (lu->tgt->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS) blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512); + blk_queue_max_segment_size(sdev->request_queue, SBP2_MAX_SEG_SIZE); + return 0; } -- cgit v1.2.3-70-g09d2 From 4bbc1bdd010cbfcb749e4f947161ec3ab3337893 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 9 Aug 2008 20:22:17 +0200 Subject: firewire: fw-sbp2: fix another small generation access bug queuecommand() looked at the remote and local node IDs before it read the bus generation. The corresponding race with sbp2_reconnect updating these data was probably impossible to happen though because the current code blocks the SCSI layer during reconnection. However, better safe than sorry, especially if someone later improves the code to not block the SCSI layer. Signed-off-by: Stefan Richter --- drivers/firewire/fw-sbp2.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/firewire/fw-sbp2.c') diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index 5d8411afced..ef0b9b419c2 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -1423,7 +1423,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) struct fw_device *device = fw_device(lu->tgt->unit->device.parent); struct sbp2_command_orb *orb; unsigned int max_payload; - int retval = SCSI_MLQUEUE_HOST_BUSY; + int generation, retval = SCSI_MLQUEUE_HOST_BUSY; /* * Bidirectional commands are not yet implemented, and unknown @@ -1467,6 +1467,9 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) if (cmd->sc_data_direction == DMA_FROM_DEVICE) orb->request.misc |= cpu_to_be32(COMMAND_ORB_DIRECTION); + generation = device->generation; + smp_rmb(); /* sbp2_map_scatterlist looks at tgt->address_high */ + if (scsi_sg_count(cmd) && sbp2_map_scatterlist(orb, device, lu) < 0) goto out; @@ -1479,7 +1482,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) if (dma_mapping_error(device->card->device, orb->base.request_bus)) goto out; - sbp2_send_orb(&orb->base, lu, lu->tgt->node_id, lu->generation, + sbp2_send_orb(&orb->base, lu, lu->tgt->node_id, generation, lu->command_block_agent_address + SBP2_ORB_POINTER); retval = 0; out: -- cgit v1.2.3-70-g09d2