aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ieee1394/sbp2.c
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2008-08-14 03:28:14 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2008-10-15 16:21:07 -0400
commited6ffd08084c68e9c3911e27706dec9d4c9a4175 (patch)
treee13379a355b162636c8e06a82b71c2d145de5708 /drivers/ieee1394/sbp2.c
parentcd8c79f17a878b01f3e83a8efd89da18ccdc7ef3 (diff)
ieee1394: 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 ieee1394 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. We can also uniformly use dma_map_sg() for the single segment case just like for the multi segment case, to further simplify the code. Also clean up how the page table is converted to big endian. Thanks to Grant Grundler and FUJITA Tomonori for advice. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/ieee1394/sbp2.c')
-rw-r--r--drivers/ieee1394/sbp2.c98
1 files changed, 28 insertions, 70 deletions
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 0037305f599e..c52f6e6e8af2 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -656,24 +656,11 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb(
656static void sbp2util_mark_command_completed(struct sbp2_lu *lu, 656static void sbp2util_mark_command_completed(struct sbp2_lu *lu,
657 struct sbp2_command_info *cmd) 657 struct sbp2_command_info *cmd)
658{ 658{
659 struct hpsb_host *host = lu->ud->ne->host; 659 if (scsi_sg_count(cmd->Current_SCpnt))
660 660 dma_unmap_sg(lu->ud->ne->host->device.parent,
661 if (cmd->cmd_dma) { 661 scsi_sglist(cmd->Current_SCpnt),
662 if (cmd->dma_type == CMD_DMA_SINGLE) 662 scsi_sg_count(cmd->Current_SCpnt),
663 dma_unmap_single(host->device.parent, cmd->cmd_dma, 663 cmd->Current_SCpnt->sc_data_direction);
664 cmd->dma_size, cmd->dma_dir);
665 else if (cmd->dma_type == CMD_DMA_PAGE)
666 dma_unmap_page(host->device.parent, cmd->cmd_dma,
667 cmd->dma_size, cmd->dma_dir);
668 /* XXX: Check for CMD_DMA_NONE bug */
669 cmd->dma_type = CMD_DMA_NONE;
670 cmd->cmd_dma = 0;
671 }
672 if (cmd->sge_buffer) {
673 dma_unmap_sg(host->device.parent, cmd->sge_buffer,
674 cmd->dma_size, cmd->dma_dir);
675 cmd->sge_buffer = NULL;
676 }
677 list_move_tail(&cmd->list, &lu->cmd_orb_completed); 664 list_move_tail(&cmd->list, &lu->cmd_orb_completed);
678} 665}
679 666
@@ -838,6 +825,10 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud)
838#endif 825#endif
839 } 826 }
840 827
828 if (dma_get_max_seg_size(hi->host->device.parent) > SBP2_MAX_SEG_SIZE)
829 BUG_ON(dma_set_max_seg_size(hi->host->device.parent,
830 SBP2_MAX_SEG_SIZE));
831
841 /* Prevent unloading of the 1394 host */ 832 /* Prevent unloading of the 1394 host */
842 if (!try_module_get(hi->host->driver->owner)) { 833 if (!try_module_get(hi->host->driver->owner)) {
843 SBP2_ERR("failed to get a reference on 1394 host driver"); 834 SBP2_ERR("failed to get a reference on 1394 host driver");
@@ -1512,76 +1503,41 @@ static int sbp2_agent_reset(struct sbp2_lu *lu, int wait)
1512static int sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb, 1503static int sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
1513 struct sbp2_fwhost_info *hi, 1504 struct sbp2_fwhost_info *hi,
1514 struct sbp2_command_info *cmd, 1505 struct sbp2_command_info *cmd,
1515 unsigned int scsi_use_sg, 1506 unsigned int sg_count,
1516 struct scatterlist *sg, 1507 struct scatterlist *sg,
1517 u32 orb_direction, 1508 u32 orb_direction,
1518 enum dma_data_direction dma_dir) 1509 enum dma_data_direction dma_dir)
1519{ 1510{
1520 struct device *dmadev = hi->host->device.parent; 1511 struct device *dmadev = hi->host->device.parent;
1512 struct sbp2_unrestricted_page_table *pt;
1513 int i, n;
1514
1515 n = dma_map_sg(dmadev, sg, sg_count, dma_dir);
1516 if (n == 0)
1517 return -ENOMEM;
1521 1518
1522 cmd->dma_dir = dma_dir;
1523 orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id); 1519 orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
1524 orb->misc |= ORB_SET_DIRECTION(orb_direction); 1520 orb->misc |= ORB_SET_DIRECTION(orb_direction);
1525 1521
1526 /* special case if only one element (and less than 64KB in size) */ 1522 /* special case if only one element (and less than 64KB in size) */
1527 if (scsi_use_sg == 1 && sg->length <= SBP2_MAX_SG_ELEMENT_LENGTH) { 1523 if (n == 1) {
1528 1524 orb->misc |= ORB_SET_DATA_SIZE(sg_dma_len(sg));
1529 cmd->dma_size = sg->length; 1525 orb->data_descriptor_lo = sg_dma_address(sg);
1530 cmd->dma_type = CMD_DMA_PAGE;
1531 cmd->cmd_dma = dma_map_page(dmadev, sg_page(sg), sg->offset,
1532 cmd->dma_size, cmd->dma_dir);
1533 if (dma_mapping_error(dmadev, cmd->cmd_dma)) {
1534 cmd->cmd_dma = 0;
1535 return -ENOMEM;
1536 }
1537
1538 orb->data_descriptor_lo = cmd->cmd_dma;
1539 orb->misc |= ORB_SET_DATA_SIZE(cmd->dma_size);
1540
1541 } else { 1526 } else {
1542 struct sbp2_unrestricted_page_table *sg_element = 1527 pt = &cmd->scatter_gather_element[0];
1543 &cmd->scatter_gather_element[0];
1544 u32 sg_count, sg_len;
1545 dma_addr_t sg_addr;
1546 int i, count = dma_map_sg(dmadev, sg, scsi_use_sg, dma_dir);
1547
1548 cmd->dma_size = scsi_use_sg;
1549 cmd->sge_buffer = sg;
1550
1551 /* use page tables (s/g) */
1552 orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
1553 orb->data_descriptor_lo = cmd->sge_dma;
1554 1528
1555 dma_sync_single_for_cpu(dmadev, cmd->sge_dma, 1529 dma_sync_single_for_cpu(dmadev, cmd->sge_dma,
1556 sizeof(cmd->scatter_gather_element), 1530 sizeof(cmd->scatter_gather_element),
1557 DMA_TO_DEVICE); 1531 DMA_TO_DEVICE);
1558 1532
1559 /* loop through and fill out our SBP-2 page tables 1533 for_each_sg(sg, sg, n, i) {
1560 * (and split up anything too large) */ 1534 pt[i].high = cpu_to_be32(sg_dma_len(sg) << 16);
1561 for (i = 0, sg_count = 0; i < count; i++, sg = sg_next(sg)) { 1535 pt[i].low = cpu_to_be32(sg_dma_address(sg));
1562 sg_len = sg_dma_len(sg);
1563 sg_addr = sg_dma_address(sg);
1564 while (sg_len) {
1565 sg_element[sg_count].segment_base_lo = sg_addr;
1566 if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
1567 sg_element[sg_count].length_segment_base_hi =
1568 PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
1569 sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
1570 sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
1571 } else {
1572 sg_element[sg_count].length_segment_base_hi =
1573 PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
1574 sg_len = 0;
1575 }
1576 sg_count++;
1577 }
1578 } 1536 }
1579 1537
1580 orb->misc |= ORB_SET_DATA_SIZE(sg_count); 1538 orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1) |
1581 1539 ORB_SET_DATA_SIZE(n);
1582 sbp2util_cpu_to_be32_buffer(sg_element, 1540 orb->data_descriptor_lo = cmd->sge_dma;
1583 (sizeof(struct sbp2_unrestricted_page_table)) *
1584 sg_count);
1585 1541
1586 dma_sync_single_for_device(dmadev, cmd->sge_dma, 1542 dma_sync_single_for_device(dmadev, cmd->sge_dma,
1587 sizeof(cmd->scatter_gather_element), 1543 sizeof(cmd->scatter_gather_element),
@@ -2048,6 +2004,8 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev)
2048 sdev->start_stop_pwr_cond = 1; 2004 sdev->start_stop_pwr_cond = 1;
2049 if (lu->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS) 2005 if (lu->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
2050 blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512); 2006 blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
2007
2008 blk_queue_max_segment_size(sdev->request_queue, SBP2_MAX_SEG_SIZE);
2051 return 0; 2009 return 0;
2052} 2010}
2053 2011