diff options
Diffstat (limited to 'drivers/ieee1394/sbp2.c')
-rw-r--r-- | drivers/ieee1394/sbp2.c | 218 |
1 files changed, 91 insertions, 127 deletions
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 1d6ad3435537..c52f6e6e8af2 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c | |||
@@ -526,26 +526,41 @@ static void sbp2util_write_doorbell(struct work_struct *work) | |||
526 | 526 | ||
527 | static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu) | 527 | static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu) |
528 | { | 528 | { |
529 | struct sbp2_fwhost_info *hi = lu->hi; | ||
530 | struct sbp2_command_info *cmd; | 529 | struct sbp2_command_info *cmd; |
530 | struct device *dmadev = lu->hi->host->device.parent; | ||
531 | int i, orbs = sbp2_serialize_io ? 2 : SBP2_MAX_CMDS; | 531 | int i, orbs = sbp2_serialize_io ? 2 : SBP2_MAX_CMDS; |
532 | 532 | ||
533 | for (i = 0; i < orbs; i++) { | 533 | for (i = 0; i < orbs; i++) { |
534 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 534 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
535 | if (!cmd) | 535 | if (!cmd) |
536 | return -ENOMEM; | 536 | goto failed_alloc; |
537 | cmd->command_orb_dma = dma_map_single(hi->host->device.parent, | 537 | |
538 | &cmd->command_orb, | 538 | cmd->command_orb_dma = |
539 | sizeof(struct sbp2_command_orb), | 539 | dma_map_single(dmadev, &cmd->command_orb, |
540 | DMA_TO_DEVICE); | 540 | sizeof(struct sbp2_command_orb), |
541 | cmd->sge_dma = dma_map_single(hi->host->device.parent, | 541 | DMA_TO_DEVICE); |
542 | &cmd->scatter_gather_element, | 542 | if (dma_mapping_error(dmadev, cmd->command_orb_dma)) |
543 | sizeof(cmd->scatter_gather_element), | 543 | goto failed_orb; |
544 | DMA_TO_DEVICE); | 544 | |
545 | cmd->sge_dma = | ||
546 | dma_map_single(dmadev, &cmd->scatter_gather_element, | ||
547 | sizeof(cmd->scatter_gather_element), | ||
548 | DMA_TO_DEVICE); | ||
549 | if (dma_mapping_error(dmadev, cmd->sge_dma)) | ||
550 | goto failed_sge; | ||
551 | |||
545 | INIT_LIST_HEAD(&cmd->list); | 552 | INIT_LIST_HEAD(&cmd->list); |
546 | list_add_tail(&cmd->list, &lu->cmd_orb_completed); | 553 | list_add_tail(&cmd->list, &lu->cmd_orb_completed); |
547 | } | 554 | } |
548 | return 0; | 555 | return 0; |
556 | |||
557 | failed_sge: | ||
558 | dma_unmap_single(dmadev, cmd->command_orb_dma, | ||
559 | sizeof(struct sbp2_command_orb), DMA_TO_DEVICE); | ||
560 | failed_orb: | ||
561 | kfree(cmd); | ||
562 | failed_alloc: | ||
563 | return -ENOMEM; | ||
549 | } | 564 | } |
550 | 565 | ||
551 | static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu, | 566 | static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu, |
@@ -641,24 +656,11 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb( | |||
641 | static void sbp2util_mark_command_completed(struct sbp2_lu *lu, | 656 | static void sbp2util_mark_command_completed(struct sbp2_lu *lu, |
642 | struct sbp2_command_info *cmd) | 657 | struct sbp2_command_info *cmd) |
643 | { | 658 | { |
644 | struct hpsb_host *host = lu->ud->ne->host; | 659 | if (scsi_sg_count(cmd->Current_SCpnt)) |
645 | 660 | dma_unmap_sg(lu->ud->ne->host->device.parent, | |
646 | if (cmd->cmd_dma) { | 661 | scsi_sglist(cmd->Current_SCpnt), |
647 | if (cmd->dma_type == CMD_DMA_SINGLE) | 662 | scsi_sg_count(cmd->Current_SCpnt), |
648 | dma_unmap_single(host->device.parent, cmd->cmd_dma, | 663 | cmd->Current_SCpnt->sc_data_direction); |
649 | cmd->dma_size, cmd->dma_dir); | ||
650 | else if (cmd->dma_type == CMD_DMA_PAGE) | ||
651 | dma_unmap_page(host->device.parent, cmd->cmd_dma, | ||
652 | cmd->dma_size, cmd->dma_dir); | ||
653 | /* XXX: Check for CMD_DMA_NONE bug */ | ||
654 | cmd->dma_type = CMD_DMA_NONE; | ||
655 | cmd->cmd_dma = 0; | ||
656 | } | ||
657 | if (cmd->sge_buffer) { | ||
658 | dma_unmap_sg(host->device.parent, cmd->sge_buffer, | ||
659 | cmd->dma_size, cmd->dma_dir); | ||
660 | cmd->sge_buffer = NULL; | ||
661 | } | ||
662 | list_move_tail(&cmd->list, &lu->cmd_orb_completed); | 664 | list_move_tail(&cmd->list, &lu->cmd_orb_completed); |
663 | } | 665 | } |
664 | 666 | ||
@@ -823,6 +825,10 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud) | |||
823 | #endif | 825 | #endif |
824 | } | 826 | } |
825 | 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 | |||
826 | /* Prevent unloading of the 1394 host */ | 832 | /* Prevent unloading of the 1394 host */ |
827 | if (!try_module_get(hi->host->driver->owner)) { | 833 | if (!try_module_get(hi->host->driver->owner)) { |
828 | SBP2_ERR("failed to get a reference on 1394 host driver"); | 834 | SBP2_ERR("failed to get a reference on 1394 host driver"); |
@@ -1494,84 +1500,65 @@ static int sbp2_agent_reset(struct sbp2_lu *lu, int wait) | |||
1494 | return 0; | 1500 | return 0; |
1495 | } | 1501 | } |
1496 | 1502 | ||
1497 | static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb, | 1503 | static int sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb, |
1498 | struct sbp2_fwhost_info *hi, | 1504 | struct sbp2_fwhost_info *hi, |
1499 | struct sbp2_command_info *cmd, | 1505 | struct sbp2_command_info *cmd, |
1500 | unsigned int scsi_use_sg, | 1506 | unsigned int sg_count, |
1501 | struct scatterlist *sg, | 1507 | struct scatterlist *sg, |
1502 | u32 orb_direction, | 1508 | u32 orb_direction, |
1503 | enum dma_data_direction dma_dir) | 1509 | enum dma_data_direction dma_dir) |
1504 | { | 1510 | { |
1505 | cmd->dma_dir = dma_dir; | 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; | ||
1518 | |||
1506 | 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); |
1507 | orb->misc |= ORB_SET_DIRECTION(orb_direction); | 1520 | orb->misc |= ORB_SET_DIRECTION(orb_direction); |
1508 | 1521 | ||
1509 | /* 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) */ |
1510 | if (scsi_use_sg == 1 && sg->length <= SBP2_MAX_SG_ELEMENT_LENGTH) { | 1523 | if (n == 1) { |
1511 | 1524 | orb->misc |= ORB_SET_DATA_SIZE(sg_dma_len(sg)); | |
1512 | cmd->dma_size = sg->length; | 1525 | orb->data_descriptor_lo = sg_dma_address(sg); |
1513 | cmd->dma_type = CMD_DMA_PAGE; | ||
1514 | cmd->cmd_dma = dma_map_page(hi->host->device.parent, | ||
1515 | sg_page(sg), sg->offset, | ||
1516 | cmd->dma_size, cmd->dma_dir); | ||
1517 | |||
1518 | orb->data_descriptor_lo = cmd->cmd_dma; | ||
1519 | orb->misc |= ORB_SET_DATA_SIZE(cmd->dma_size); | ||
1520 | |||
1521 | } else { | 1526 | } else { |
1522 | struct sbp2_unrestricted_page_table *sg_element = | 1527 | pt = &cmd->scatter_gather_element[0]; |
1523 | &cmd->scatter_gather_element[0]; | ||
1524 | u32 sg_count, sg_len; | ||
1525 | dma_addr_t sg_addr; | ||
1526 | int i, count = dma_map_sg(hi->host->device.parent, sg, | ||
1527 | scsi_use_sg, dma_dir); | ||
1528 | |||
1529 | cmd->dma_size = scsi_use_sg; | ||
1530 | cmd->sge_buffer = sg; | ||
1531 | |||
1532 | /* use page tables (s/g) */ | ||
1533 | orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1); | ||
1534 | orb->data_descriptor_lo = cmd->sge_dma; | ||
1535 | 1528 | ||
1536 | /* loop through and fill out our SBP-2 page tables | 1529 | dma_sync_single_for_cpu(dmadev, cmd->sge_dma, |
1537 | * (and split up anything too large) */ | 1530 | sizeof(cmd->scatter_gather_element), |
1538 | for (i = 0, sg_count = 0; i < count; i++, sg = sg_next(sg)) { | 1531 | DMA_TO_DEVICE); |
1539 | sg_len = sg_dma_len(sg); | 1532 | |
1540 | sg_addr = sg_dma_address(sg); | 1533 | for_each_sg(sg, sg, n, i) { |
1541 | while (sg_len) { | 1534 | pt[i].high = cpu_to_be32(sg_dma_len(sg) << 16); |
1542 | sg_element[sg_count].segment_base_lo = sg_addr; | 1535 | pt[i].low = cpu_to_be32(sg_dma_address(sg)); |
1543 | if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) { | ||
1544 | sg_element[sg_count].length_segment_base_hi = | ||
1545 | PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH); | ||
1546 | sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH; | ||
1547 | sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH; | ||
1548 | } else { | ||
1549 | sg_element[sg_count].length_segment_base_hi = | ||
1550 | PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len); | ||
1551 | sg_len = 0; | ||
1552 | } | ||
1553 | sg_count++; | ||
1554 | } | ||
1555 | } | 1536 | } |
1556 | 1537 | ||
1557 | orb->misc |= ORB_SET_DATA_SIZE(sg_count); | 1538 | orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1) | |
1539 | ORB_SET_DATA_SIZE(n); | ||
1540 | orb->data_descriptor_lo = cmd->sge_dma; | ||
1558 | 1541 | ||
1559 | sbp2util_cpu_to_be32_buffer(sg_element, | 1542 | dma_sync_single_for_device(dmadev, cmd->sge_dma, |
1560 | (sizeof(struct sbp2_unrestricted_page_table)) * | 1543 | sizeof(cmd->scatter_gather_element), |
1561 | sg_count); | 1544 | DMA_TO_DEVICE); |
1562 | } | 1545 | } |
1546 | return 0; | ||
1563 | } | 1547 | } |
1564 | 1548 | ||
1565 | static void sbp2_create_command_orb(struct sbp2_lu *lu, | 1549 | static int sbp2_create_command_orb(struct sbp2_lu *lu, |
1566 | struct sbp2_command_info *cmd, | 1550 | struct sbp2_command_info *cmd, |
1567 | struct scsi_cmnd *SCpnt) | 1551 | struct scsi_cmnd *SCpnt) |
1568 | { | 1552 | { |
1569 | struct sbp2_fwhost_info *hi = lu->hi; | 1553 | struct device *dmadev = lu->hi->host->device.parent; |
1570 | struct sbp2_command_orb *orb = &cmd->command_orb; | 1554 | struct sbp2_command_orb *orb = &cmd->command_orb; |
1571 | u32 orb_direction; | ||
1572 | unsigned int scsi_request_bufflen = scsi_bufflen(SCpnt); | 1555 | unsigned int scsi_request_bufflen = scsi_bufflen(SCpnt); |
1573 | enum dma_data_direction dma_dir = SCpnt->sc_data_direction; | 1556 | enum dma_data_direction dma_dir = SCpnt->sc_data_direction; |
1557 | u32 orb_direction; | ||
1558 | int ret; | ||
1574 | 1559 | ||
1560 | dma_sync_single_for_cpu(dmadev, cmd->command_orb_dma, | ||
1561 | sizeof(struct sbp2_command_orb), DMA_TO_DEVICE); | ||
1575 | /* | 1562 | /* |
1576 | * Set-up our command ORB. | 1563 | * Set-up our command ORB. |
1577 | * | 1564 | * |
@@ -1602,15 +1589,21 @@ static void sbp2_create_command_orb(struct sbp2_lu *lu, | |||
1602 | orb->data_descriptor_hi = 0x0; | 1589 | orb->data_descriptor_hi = 0x0; |
1603 | orb->data_descriptor_lo = 0x0; | 1590 | orb->data_descriptor_lo = 0x0; |
1604 | orb->misc |= ORB_SET_DIRECTION(1); | 1591 | orb->misc |= ORB_SET_DIRECTION(1); |
1605 | } else | 1592 | ret = 0; |
1606 | sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_sg_count(SCpnt), | 1593 | } else { |
1607 | scsi_sglist(SCpnt), | 1594 | ret = sbp2_prep_command_orb_sg(orb, lu->hi, cmd, |
1608 | orb_direction, dma_dir); | 1595 | scsi_sg_count(SCpnt), |
1609 | 1596 | scsi_sglist(SCpnt), | |
1597 | orb_direction, dma_dir); | ||
1598 | } | ||
1610 | sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb)); | 1599 | sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb)); |
1611 | 1600 | ||
1612 | memset(orb->cdb, 0, sizeof(orb->cdb)); | 1601 | memset(orb->cdb, 0, sizeof(orb->cdb)); |
1613 | memcpy(orb->cdb, SCpnt->cmnd, SCpnt->cmd_len); | 1602 | memcpy(orb->cdb, SCpnt->cmnd, SCpnt->cmd_len); |
1603 | |||
1604 | dma_sync_single_for_device(dmadev, cmd->command_orb_dma, | ||
1605 | sizeof(struct sbp2_command_orb), DMA_TO_DEVICE); | ||
1606 | return ret; | ||
1614 | } | 1607 | } |
1615 | 1608 | ||
1616 | static void sbp2_link_orb_command(struct sbp2_lu *lu, | 1609 | static void sbp2_link_orb_command(struct sbp2_lu *lu, |
@@ -1624,14 +1617,6 @@ static void sbp2_link_orb_command(struct sbp2_lu *lu, | |||
1624 | size_t length; | 1617 | size_t length; |
1625 | unsigned long flags; | 1618 | unsigned long flags; |
1626 | 1619 | ||
1627 | dma_sync_single_for_device(hi->host->device.parent, | ||
1628 | cmd->command_orb_dma, | ||
1629 | sizeof(struct sbp2_command_orb), | ||
1630 | DMA_TO_DEVICE); | ||
1631 | dma_sync_single_for_device(hi->host->device.parent, cmd->sge_dma, | ||
1632 | sizeof(cmd->scatter_gather_element), | ||
1633 | DMA_TO_DEVICE); | ||
1634 | |||
1635 | /* check to see if there are any previous orbs to use */ | 1620 | /* check to see if there are any previous orbs to use */ |
1636 | spin_lock_irqsave(&lu->cmd_orb_lock, flags); | 1621 | spin_lock_irqsave(&lu->cmd_orb_lock, flags); |
1637 | last_orb = lu->last_orb; | 1622 | last_orb = lu->last_orb; |
@@ -1699,9 +1684,10 @@ static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt, | |||
1699 | if (!cmd) | 1684 | if (!cmd) |
1700 | return -EIO; | 1685 | return -EIO; |
1701 | 1686 | ||
1702 | sbp2_create_command_orb(lu, cmd, SCpnt); | 1687 | if (sbp2_create_command_orb(lu, cmd, SCpnt)) |
1703 | sbp2_link_orb_command(lu, cmd); | 1688 | return -ENOMEM; |
1704 | 1689 | ||
1690 | sbp2_link_orb_command(lu, cmd); | ||
1705 | return 0; | 1691 | return 0; |
1706 | } | 1692 | } |
1707 | 1693 | ||
@@ -1789,13 +1775,6 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, | |||
1789 | else | 1775 | else |
1790 | cmd = sbp2util_find_command_for_orb(lu, sb->ORB_offset_lo); | 1776 | cmd = sbp2util_find_command_for_orb(lu, sb->ORB_offset_lo); |
1791 | if (cmd) { | 1777 | if (cmd) { |
1792 | dma_sync_single_for_cpu(hi->host->device.parent, | ||
1793 | cmd->command_orb_dma, | ||
1794 | sizeof(struct sbp2_command_orb), | ||
1795 | DMA_TO_DEVICE); | ||
1796 | dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma, | ||
1797 | sizeof(cmd->scatter_gather_element), | ||
1798 | DMA_TO_DEVICE); | ||
1799 | /* Grab SCSI command pointers and check status. */ | 1778 | /* Grab SCSI command pointers and check status. */ |
1800 | /* | 1779 | /* |
1801 | * FIXME: If the src field in the status is 1, the ORB DMA must | 1780 | * FIXME: If the src field in the status is 1, the ORB DMA must |
@@ -1912,7 +1891,6 @@ done: | |||
1912 | 1891 | ||
1913 | static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status) | 1892 | static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status) |
1914 | { | 1893 | { |
1915 | struct sbp2_fwhost_info *hi = lu->hi; | ||
1916 | struct list_head *lh; | 1894 | struct list_head *lh; |
1917 | struct sbp2_command_info *cmd; | 1895 | struct sbp2_command_info *cmd; |
1918 | unsigned long flags; | 1896 | unsigned long flags; |
@@ -1921,13 +1899,6 @@ static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status) | |||
1921 | while (!list_empty(&lu->cmd_orb_inuse)) { | 1899 | while (!list_empty(&lu->cmd_orb_inuse)) { |
1922 | lh = lu->cmd_orb_inuse.next; | 1900 | lh = lu->cmd_orb_inuse.next; |
1923 | cmd = list_entry(lh, struct sbp2_command_info, list); | 1901 | cmd = list_entry(lh, struct sbp2_command_info, list); |
1924 | dma_sync_single_for_cpu(hi->host->device.parent, | ||
1925 | cmd->command_orb_dma, | ||
1926 | sizeof(struct sbp2_command_orb), | ||
1927 | DMA_TO_DEVICE); | ||
1928 | dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma, | ||
1929 | sizeof(cmd->scatter_gather_element), | ||
1930 | DMA_TO_DEVICE); | ||
1931 | sbp2util_mark_command_completed(lu, cmd); | 1902 | sbp2util_mark_command_completed(lu, cmd); |
1932 | if (cmd->Current_SCpnt) { | 1903 | if (cmd->Current_SCpnt) { |
1933 | cmd->Current_SCpnt->result = status << 16; | 1904 | cmd->Current_SCpnt->result = status << 16; |
@@ -2033,6 +2004,8 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev) | |||
2033 | sdev->start_stop_pwr_cond = 1; | 2004 | sdev->start_stop_pwr_cond = 1; |
2034 | if (lu->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS) | 2005 | if (lu->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS) |
2035 | 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); | ||
2036 | return 0; | 2009 | return 0; |
2037 | } | 2010 | } |
2038 | 2011 | ||
@@ -2049,7 +2022,6 @@ static void sbp2scsi_slave_destroy(struct scsi_device *sdev) | |||
2049 | static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) | 2022 | static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) |
2050 | { | 2023 | { |
2051 | struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0]; | 2024 | struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0]; |
2052 | struct sbp2_fwhost_info *hi = lu->hi; | ||
2053 | struct sbp2_command_info *cmd; | 2025 | struct sbp2_command_info *cmd; |
2054 | unsigned long flags; | 2026 | unsigned long flags; |
2055 | 2027 | ||
@@ -2063,14 +2035,6 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) | |||
2063 | spin_lock_irqsave(&lu->cmd_orb_lock, flags); | 2035 | spin_lock_irqsave(&lu->cmd_orb_lock, flags); |
2064 | cmd = sbp2util_find_command_for_SCpnt(lu, SCpnt); | 2036 | cmd = sbp2util_find_command_for_SCpnt(lu, SCpnt); |
2065 | if (cmd) { | 2037 | if (cmd) { |
2066 | dma_sync_single_for_cpu(hi->host->device.parent, | ||
2067 | cmd->command_orb_dma, | ||
2068 | sizeof(struct sbp2_command_orb), | ||
2069 | DMA_TO_DEVICE); | ||
2070 | dma_sync_single_for_cpu(hi->host->device.parent, | ||
2071 | cmd->sge_dma, | ||
2072 | sizeof(cmd->scatter_gather_element), | ||
2073 | DMA_TO_DEVICE); | ||
2074 | sbp2util_mark_command_completed(lu, cmd); | 2038 | sbp2util_mark_command_completed(lu, cmd); |
2075 | if (cmd->Current_SCpnt) { | 2039 | if (cmd->Current_SCpnt) { |
2076 | cmd->Current_SCpnt->result = DID_ABORT << 16; | 2040 | cmd->Current_SCpnt->result = DID_ABORT << 16; |