.. | .. |
---|
56 | 56 | #include <linux/mutex.h> |
---|
57 | 57 | |
---|
58 | 58 | #include <asm/processor.h> /* for boot_cpu_data */ |
---|
59 | | -#include <asm/io.h> /* for virt_to_bus, etc. */ |
---|
| 59 | +#include <asm/io.h> |
---|
60 | 60 | |
---|
61 | 61 | #include <scsi/scsi.h> |
---|
62 | 62 | #include <scsi/scsi_cmnd.h> |
---|
.. | .. |
---|
580 | 580 | } |
---|
581 | 581 | } |
---|
582 | 582 | return 0; |
---|
583 | | -} |
---|
584 | | - |
---|
585 | | -/* |
---|
586 | | - * Turn a pointer to ioctl reply data into an u32 'context' |
---|
587 | | - */ |
---|
588 | | -static u32 adpt_ioctl_to_context(adpt_hba * pHba, void *reply) |
---|
589 | | -{ |
---|
590 | | -#if BITS_PER_LONG == 32 |
---|
591 | | - return (u32)(unsigned long)reply; |
---|
592 | | -#else |
---|
593 | | - ulong flags = 0; |
---|
594 | | - u32 nr, i; |
---|
595 | | - |
---|
596 | | - spin_lock_irqsave(pHba->host->host_lock, flags); |
---|
597 | | - nr = ARRAY_SIZE(pHba->ioctl_reply_context); |
---|
598 | | - for (i = 0; i < nr; i++) { |
---|
599 | | - if (pHba->ioctl_reply_context[i] == NULL) { |
---|
600 | | - pHba->ioctl_reply_context[i] = reply; |
---|
601 | | - break; |
---|
602 | | - } |
---|
603 | | - } |
---|
604 | | - spin_unlock_irqrestore(pHba->host->host_lock, flags); |
---|
605 | | - if (i >= nr) { |
---|
606 | | - printk(KERN_WARNING"%s: Too many outstanding " |
---|
607 | | - "ioctl commands\n", pHba->name); |
---|
608 | | - return (u32)-1; |
---|
609 | | - } |
---|
610 | | - |
---|
611 | | - return i; |
---|
612 | | -#endif |
---|
613 | | -} |
---|
614 | | - |
---|
615 | | -/* |
---|
616 | | - * Go from an u32 'context' to a pointer to ioctl reply data. |
---|
617 | | - */ |
---|
618 | | -static void *adpt_ioctl_from_context(adpt_hba *pHba, u32 context) |
---|
619 | | -{ |
---|
620 | | -#if BITS_PER_LONG == 32 |
---|
621 | | - return (void *)(unsigned long)context; |
---|
622 | | -#else |
---|
623 | | - void *p = pHba->ioctl_reply_context[context]; |
---|
624 | | - pHba->ioctl_reply_context[context] = NULL; |
---|
625 | | - |
---|
626 | | - return p; |
---|
627 | | -#endif |
---|
628 | 583 | } |
---|
629 | 584 | |
---|
630 | 585 | /*=========================================================================== |
---|
.. | .. |
---|
1648 | 1603 | return 0; |
---|
1649 | 1604 | } |
---|
1650 | 1605 | |
---|
1651 | | - |
---|
1652 | | -static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg) |
---|
1653 | | -{ |
---|
1654 | | - u32 msg[MAX_MESSAGE_SIZE]; |
---|
1655 | | - u32* reply = NULL; |
---|
1656 | | - u32 size = 0; |
---|
1657 | | - u32 reply_size = 0; |
---|
1658 | | - u32 __user *user_msg = arg; |
---|
1659 | | - u32 __user * user_reply = NULL; |
---|
1660 | | - void **sg_list = NULL; |
---|
1661 | | - u32 sg_offset = 0; |
---|
1662 | | - u32 sg_count = 0; |
---|
1663 | | - int sg_index = 0; |
---|
1664 | | - u32 i = 0; |
---|
1665 | | - u32 rcode = 0; |
---|
1666 | | - void *p = NULL; |
---|
1667 | | - dma_addr_t addr; |
---|
1668 | | - ulong flags = 0; |
---|
1669 | | - |
---|
1670 | | - memset(&msg, 0, MAX_MESSAGE_SIZE*4); |
---|
1671 | | - // get user msg size in u32s |
---|
1672 | | - if(get_user(size, &user_msg[0])){ |
---|
1673 | | - return -EFAULT; |
---|
1674 | | - } |
---|
1675 | | - size = size>>16; |
---|
1676 | | - |
---|
1677 | | - user_reply = &user_msg[size]; |
---|
1678 | | - if(size > MAX_MESSAGE_SIZE){ |
---|
1679 | | - return -EFAULT; |
---|
1680 | | - } |
---|
1681 | | - size *= 4; // Convert to bytes |
---|
1682 | | - |
---|
1683 | | - /* Copy in the user's I2O command */ |
---|
1684 | | - if(copy_from_user(msg, user_msg, size)) { |
---|
1685 | | - return -EFAULT; |
---|
1686 | | - } |
---|
1687 | | - get_user(reply_size, &user_reply[0]); |
---|
1688 | | - reply_size = reply_size>>16; |
---|
1689 | | - if(reply_size > REPLY_FRAME_SIZE){ |
---|
1690 | | - reply_size = REPLY_FRAME_SIZE; |
---|
1691 | | - } |
---|
1692 | | - reply_size *= 4; |
---|
1693 | | - reply = kzalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL); |
---|
1694 | | - if(reply == NULL) { |
---|
1695 | | - printk(KERN_WARNING"%s: Could not allocate reply buffer\n",pHba->name); |
---|
1696 | | - return -ENOMEM; |
---|
1697 | | - } |
---|
1698 | | - sg_offset = (msg[0]>>4)&0xf; |
---|
1699 | | - msg[2] = 0x40000000; // IOCTL context |
---|
1700 | | - msg[3] = adpt_ioctl_to_context(pHba, reply); |
---|
1701 | | - if (msg[3] == (u32)-1) { |
---|
1702 | | - rcode = -EBUSY; |
---|
1703 | | - goto free; |
---|
1704 | | - } |
---|
1705 | | - |
---|
1706 | | - sg_list = kcalloc(pHba->sg_tablesize, sizeof(*sg_list), GFP_KERNEL); |
---|
1707 | | - if (!sg_list) { |
---|
1708 | | - rcode = -ENOMEM; |
---|
1709 | | - goto free; |
---|
1710 | | - } |
---|
1711 | | - if(sg_offset) { |
---|
1712 | | - // TODO add 64 bit API |
---|
1713 | | - struct sg_simple_element *sg = (struct sg_simple_element*) (msg+sg_offset); |
---|
1714 | | - sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element); |
---|
1715 | | - if (sg_count > pHba->sg_tablesize){ |
---|
1716 | | - printk(KERN_DEBUG"%s:IOCTL SG List too large (%u)\n", pHba->name,sg_count); |
---|
1717 | | - rcode = -EINVAL; |
---|
1718 | | - goto free; |
---|
1719 | | - } |
---|
1720 | | - |
---|
1721 | | - for(i = 0; i < sg_count; i++) { |
---|
1722 | | - int sg_size; |
---|
1723 | | - |
---|
1724 | | - if (!(sg[i].flag_count & 0x10000000 /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT*/)) { |
---|
1725 | | - printk(KERN_DEBUG"%s:Bad SG element %d - not simple (%x)\n",pHba->name,i, sg[i].flag_count); |
---|
1726 | | - rcode = -EINVAL; |
---|
1727 | | - goto cleanup; |
---|
1728 | | - } |
---|
1729 | | - sg_size = sg[i].flag_count & 0xffffff; |
---|
1730 | | - /* Allocate memory for the transfer */ |
---|
1731 | | - p = dma_alloc_coherent(&pHba->pDev->dev, sg_size, &addr, GFP_KERNEL); |
---|
1732 | | - if(!p) { |
---|
1733 | | - printk(KERN_DEBUG"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", |
---|
1734 | | - pHba->name,sg_size,i,sg_count); |
---|
1735 | | - rcode = -ENOMEM; |
---|
1736 | | - goto cleanup; |
---|
1737 | | - } |
---|
1738 | | - sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame. |
---|
1739 | | - /* Copy in the user's SG buffer if necessary */ |
---|
1740 | | - if(sg[i].flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR*/) { |
---|
1741 | | - // sg_simple_element API is 32 bit |
---|
1742 | | - if (copy_from_user(p,(void __user *)(ulong)sg[i].addr_bus, sg_size)) { |
---|
1743 | | - printk(KERN_DEBUG"%s: Could not copy SG buf %d FROM user\n",pHba->name,i); |
---|
1744 | | - rcode = -EFAULT; |
---|
1745 | | - goto cleanup; |
---|
1746 | | - } |
---|
1747 | | - } |
---|
1748 | | - /* sg_simple_element API is 32 bit, but addr < 4GB */ |
---|
1749 | | - sg[i].addr_bus = addr; |
---|
1750 | | - } |
---|
1751 | | - } |
---|
1752 | | - |
---|
1753 | | - do { |
---|
1754 | | - /* |
---|
1755 | | - * Stop any new commands from enterring the |
---|
1756 | | - * controller while processing the ioctl |
---|
1757 | | - */ |
---|
1758 | | - if (pHba->host) { |
---|
1759 | | - scsi_block_requests(pHba->host); |
---|
1760 | | - spin_lock_irqsave(pHba->host->host_lock, flags); |
---|
1761 | | - } |
---|
1762 | | - rcode = adpt_i2o_post_wait(pHba, msg, size, FOREVER); |
---|
1763 | | - if (rcode != 0) |
---|
1764 | | - printk("adpt_i2o_passthru: post wait failed %d %p\n", |
---|
1765 | | - rcode, reply); |
---|
1766 | | - if (pHba->host) { |
---|
1767 | | - spin_unlock_irqrestore(pHba->host->host_lock, flags); |
---|
1768 | | - scsi_unblock_requests(pHba->host); |
---|
1769 | | - } |
---|
1770 | | - } while (rcode == -ETIMEDOUT); |
---|
1771 | | - |
---|
1772 | | - if(rcode){ |
---|
1773 | | - goto cleanup; |
---|
1774 | | - } |
---|
1775 | | - |
---|
1776 | | - if(sg_offset) { |
---|
1777 | | - /* Copy back the Scatter Gather buffers back to user space */ |
---|
1778 | | - u32 j; |
---|
1779 | | - // TODO add 64 bit API |
---|
1780 | | - struct sg_simple_element* sg; |
---|
1781 | | - int sg_size; |
---|
1782 | | - |
---|
1783 | | - // re-acquire the original message to handle correctly the sg copy operation |
---|
1784 | | - memset(&msg, 0, MAX_MESSAGE_SIZE*4); |
---|
1785 | | - // get user msg size in u32s |
---|
1786 | | - if(get_user(size, &user_msg[0])){ |
---|
1787 | | - rcode = -EFAULT; |
---|
1788 | | - goto cleanup; |
---|
1789 | | - } |
---|
1790 | | - size = size>>16; |
---|
1791 | | - size *= 4; |
---|
1792 | | - if (size > MAX_MESSAGE_SIZE) { |
---|
1793 | | - rcode = -EINVAL; |
---|
1794 | | - goto cleanup; |
---|
1795 | | - } |
---|
1796 | | - /* Copy in the user's I2O command */ |
---|
1797 | | - if (copy_from_user (msg, user_msg, size)) { |
---|
1798 | | - rcode = -EFAULT; |
---|
1799 | | - goto cleanup; |
---|
1800 | | - } |
---|
1801 | | - sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element); |
---|
1802 | | - |
---|
1803 | | - // TODO add 64 bit API |
---|
1804 | | - sg = (struct sg_simple_element*)(msg + sg_offset); |
---|
1805 | | - for (j = 0; j < sg_count; j++) { |
---|
1806 | | - /* Copy out the SG list to user's buffer if necessary */ |
---|
1807 | | - if(! (sg[j].flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR*/)) { |
---|
1808 | | - sg_size = sg[j].flag_count & 0xffffff; |
---|
1809 | | - // sg_simple_element API is 32 bit |
---|
1810 | | - if (copy_to_user((void __user *)(ulong)sg[j].addr_bus,sg_list[j], sg_size)) { |
---|
1811 | | - printk(KERN_WARNING"%s: Could not copy %p TO user %x\n",pHba->name, sg_list[j], sg[j].addr_bus); |
---|
1812 | | - rcode = -EFAULT; |
---|
1813 | | - goto cleanup; |
---|
1814 | | - } |
---|
1815 | | - } |
---|
1816 | | - } |
---|
1817 | | - } |
---|
1818 | | - |
---|
1819 | | - /* Copy back the reply to user space */ |
---|
1820 | | - if (reply_size) { |
---|
1821 | | - // we wrote our own values for context - now restore the user supplied ones |
---|
1822 | | - if(copy_from_user(reply+2, user_msg+2, sizeof(u32)*2)) { |
---|
1823 | | - printk(KERN_WARNING"%s: Could not copy message context FROM user\n",pHba->name); |
---|
1824 | | - rcode = -EFAULT; |
---|
1825 | | - } |
---|
1826 | | - if(copy_to_user(user_reply, reply, reply_size)) { |
---|
1827 | | - printk(KERN_WARNING"%s: Could not copy reply TO user\n",pHba->name); |
---|
1828 | | - rcode = -EFAULT; |
---|
1829 | | - } |
---|
1830 | | - } |
---|
1831 | | - |
---|
1832 | | - |
---|
1833 | | -cleanup: |
---|
1834 | | - if (rcode != -ETIME && rcode != -EINTR) { |
---|
1835 | | - struct sg_simple_element *sg = |
---|
1836 | | - (struct sg_simple_element*) (msg +sg_offset); |
---|
1837 | | - while(sg_index) { |
---|
1838 | | - if(sg_list[--sg_index]) { |
---|
1839 | | - dma_free_coherent(&pHba->pDev->dev, |
---|
1840 | | - sg[sg_index].flag_count & 0xffffff, |
---|
1841 | | - sg_list[sg_index], |
---|
1842 | | - sg[sg_index].addr_bus); |
---|
1843 | | - } |
---|
1844 | | - } |
---|
1845 | | - } |
---|
1846 | | - |
---|
1847 | | -free: |
---|
1848 | | - kfree(sg_list); |
---|
1849 | | - kfree(reply); |
---|
1850 | | - return rcode; |
---|
1851 | | -} |
---|
1852 | | - |
---|
1853 | 1606 | #if defined __ia64__ |
---|
1854 | 1607 | static void adpt_ia64_info(sysInfo_S* si) |
---|
1855 | 1608 | { |
---|
.. | .. |
---|
1976 | 1729 | return -EFAULT; |
---|
1977 | 1730 | } |
---|
1978 | 1731 | break; |
---|
1979 | | - case I2OUSRCMD: |
---|
1980 | | - return adpt_i2o_passthru(pHba, argp); |
---|
1981 | 1732 | |
---|
1982 | 1733 | case DPT_CTRLINFO:{ |
---|
1983 | 1734 | drvrHBAinfo_S HbaInfo; |
---|
.. | .. |
---|
2114 | 1865 | } else { |
---|
2115 | 1866 | /* Ick, we should *never* be here */ |
---|
2116 | 1867 | printk(KERN_ERR "dpti: reply frame not from pool\n"); |
---|
2117 | | - reply = (u8 *)bus_to_virt(m); |
---|
| 1868 | + continue; |
---|
2118 | 1869 | } |
---|
2119 | 1870 | |
---|
2120 | 1871 | if (readl(reply) & MSG_FAIL) { |
---|
.. | .. |
---|
2134 | 1885 | adpt_send_nop(pHba, old_m); |
---|
2135 | 1886 | } |
---|
2136 | 1887 | context = readl(reply+8); |
---|
2137 | | - if(context & 0x40000000){ // IOCTL |
---|
2138 | | - void *p = adpt_ioctl_from_context(pHba, readl(reply+12)); |
---|
2139 | | - if( p != NULL) { |
---|
2140 | | - memcpy_fromio(p, reply, REPLY_FRAME_SIZE * 4); |
---|
2141 | | - } |
---|
2142 | | - // All IOCTLs will also be post wait |
---|
2143 | | - } |
---|
2144 | 1888 | if(context & 0x80000000){ // Post wait message |
---|
2145 | 1889 | status = readl(reply+16); |
---|
2146 | 1890 | if(status >> 24){ |
---|
.. | .. |
---|
2148 | 1892 | } else { |
---|
2149 | 1893 | status = I2O_POST_WAIT_OK; |
---|
2150 | 1894 | } |
---|
2151 | | - if(!(context & 0x40000000)) { |
---|
2152 | | - /* |
---|
2153 | | - * The request tag is one less than the command tag |
---|
2154 | | - * as the firmware might treat a 0 tag as invalid |
---|
2155 | | - */ |
---|
2156 | | - cmd = scsi_host_find_tag(pHba->host, |
---|
2157 | | - readl(reply + 12) - 1); |
---|
2158 | | - if(cmd != NULL) { |
---|
2159 | | - printk(KERN_WARNING"%s: Apparent SCSI cmd in Post Wait Context - cmd=%p context=%x\n", pHba->name, cmd, context); |
---|
2160 | | - } |
---|
| 1895 | + /* |
---|
| 1896 | + * The request tag is one less than the command tag |
---|
| 1897 | + * as the firmware might treat a 0 tag as invalid |
---|
| 1898 | + */ |
---|
| 1899 | + cmd = scsi_host_find_tag(pHba->host, |
---|
| 1900 | + readl(reply + 12) - 1); |
---|
| 1901 | + if(cmd != NULL) { |
---|
| 1902 | + printk(KERN_WARNING"%s: Apparent SCSI cmd in Post Wait Context - cmd=%p context=%x\n", pHba->name, cmd, context); |
---|
2161 | 1903 | } |
---|
2162 | 1904 | adpt_i2o_post_wait_complete(context, status); |
---|
2163 | 1905 | } else { // SCSI message |
---|