aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
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')
-rw-r--r--drivers/ieee1394/sbp2.c98
-rw-r--r--drivers/ieee1394/sbp2.h33
2 files changed, 39 insertions, 92 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
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index 875428bc8d29..c5036f1cc5b0 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -139,13 +139,10 @@ struct sbp2_logout_orb {
139 u32 status_fifo_lo; 139 u32 status_fifo_lo;
140} __attribute__((packed)); 140} __attribute__((packed));
141 141
142#define PAGE_TABLE_SET_SEGMENT_BASE_HI(v) ((v) & 0xffff)
143#define PAGE_TABLE_SET_SEGMENT_LENGTH(v) (((v) & 0xffff) << 16)
144
145struct sbp2_unrestricted_page_table { 142struct sbp2_unrestricted_page_table {
146 u32 length_segment_base_hi; 143 __be32 high;
147 u32 segment_base_lo; 144 __be32 low;
148} __attribute__((packed)); 145};
149 146
150#define RESP_STATUS_REQUEST_COMPLETE 0x0 147#define RESP_STATUS_REQUEST_COMPLETE 0x0
151#define RESP_STATUS_TRANSPORT_FAILURE 0x1 148#define RESP_STATUS_TRANSPORT_FAILURE 0x1
@@ -216,15 +213,18 @@ struct sbp2_status_block {
216#define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e 213#define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e
217#define SBP2_SW_VERSION_ENTRY 0x00010483 214#define SBP2_SW_VERSION_ENTRY 0x00010483
218 215
219
220/* 216/*
221 * SCSI specific definitions 217 * The default maximum s/g segment size of a FireWire controller is
218 * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to
219 * be quadlet-aligned, we set the length limit to 0xffff & ~3.
222 */ 220 */
221#define SBP2_MAX_SEG_SIZE 0xfffc
223 222
224#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000 223/*
225/* There is no real limitation of the queue depth (i.e. length of the linked 224 * There is no real limitation of the queue depth (i.e. length of the linked
226 * list of command ORBs) at the target. The chosen depth is merely an 225 * list of command ORBs) at the target. The chosen depth is merely an
227 * implementation detail of the sbp2 driver. */ 226 * implementation detail of the sbp2 driver.
227 */
228#define SBP2_MAX_CMDS 8 228#define SBP2_MAX_CMDS 8
229 229
230#define SBP2_SCSI_STATUS_GOOD 0x0 230#define SBP2_SCSI_STATUS_GOOD 0x0
@@ -240,12 +240,6 @@ struct sbp2_status_block {
240 * Representations of commands and devices 240 * Representations of commands and devices
241 */ 241 */
242 242
243enum sbp2_dma_types {
244 CMD_DMA_NONE,
245 CMD_DMA_PAGE,
246 CMD_DMA_SINGLE
247};
248
249/* Per SCSI command */ 243/* Per SCSI command */
250struct sbp2_command_info { 244struct sbp2_command_info {
251 struct list_head list; 245 struct list_head list;
@@ -258,11 +252,6 @@ struct sbp2_command_info {
258 struct sbp2_unrestricted_page_table 252 struct sbp2_unrestricted_page_table
259 scatter_gather_element[SG_ALL] __attribute__((aligned(8))); 253 scatter_gather_element[SG_ALL] __attribute__((aligned(8)));
260 dma_addr_t sge_dma; 254 dma_addr_t sge_dma;
261 void *sge_buffer;
262 dma_addr_t cmd_dma;
263 enum sbp2_dma_types dma_type;
264 unsigned long dma_size;
265 enum dma_data_direction dma_dir;
266}; 255};
267 256
268/* Per FireWire host */ 257/* Per FireWire host */