diff options
Diffstat (limited to 'drivers/scsi/ibmvscsi/ibmvfc.c')
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvfc.c | 335 |
1 files changed, 319 insertions, 16 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index bb2c696c006a..87b536a97cb4 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <scsi/scsi_device.h> | 39 | #include <scsi/scsi_device.h> |
40 | #include <scsi/scsi_tcq.h> | 40 | #include <scsi/scsi_tcq.h> |
41 | #include <scsi/scsi_transport_fc.h> | 41 | #include <scsi/scsi_transport_fc.h> |
42 | #include <scsi/scsi_bsg_fc.h> | ||
42 | #include "ibmvfc.h" | 43 | #include "ibmvfc.h" |
43 | 44 | ||
44 | static unsigned int init_timeout = IBMVFC_INIT_TIMEOUT; | 45 | static unsigned int init_timeout = IBMVFC_INIT_TIMEOUT; |
@@ -558,12 +559,11 @@ static void ibmvfc_link_down(struct ibmvfc_host *vhost, | |||
558 | /** | 559 | /** |
559 | * ibmvfc_init_host - Start host initialization | 560 | * ibmvfc_init_host - Start host initialization |
560 | * @vhost: ibmvfc host struct | 561 | * @vhost: ibmvfc host struct |
561 | * @relogin: is this a re-login? | ||
562 | * | 562 | * |
563 | * Return value: | 563 | * Return value: |
564 | * nothing | 564 | * nothing |
565 | **/ | 565 | **/ |
566 | static void ibmvfc_init_host(struct ibmvfc_host *vhost, int relogin) | 566 | static void ibmvfc_init_host(struct ibmvfc_host *vhost) |
567 | { | 567 | { |
568 | struct ibmvfc_target *tgt; | 568 | struct ibmvfc_target *tgt; |
569 | 569 | ||
@@ -577,10 +577,8 @@ static void ibmvfc_init_host(struct ibmvfc_host *vhost, int relogin) | |||
577 | } | 577 | } |
578 | 578 | ||
579 | if (!ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) { | 579 | if (!ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) { |
580 | if (!relogin) { | 580 | memset(vhost->async_crq.msgs, 0, PAGE_SIZE); |
581 | memset(vhost->async_crq.msgs, 0, PAGE_SIZE); | 581 | vhost->async_crq.cur = 0; |
582 | vhost->async_crq.cur = 0; | ||
583 | } | ||
584 | 582 | ||
585 | list_for_each_entry(tgt, &vhost->targets, queue) | 583 | list_for_each_entry(tgt, &vhost->targets, queue) |
586 | ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); | 584 | ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); |
@@ -1678,6 +1676,276 @@ static void ibmvfc_sync_completion(struct ibmvfc_event *evt) | |||
1678 | } | 1676 | } |
1679 | 1677 | ||
1680 | /** | 1678 | /** |
1679 | * ibmvfc_bsg_timeout_done - Completion handler for cancelling BSG commands | ||
1680 | * @evt: struct ibmvfc_event | ||
1681 | * | ||
1682 | **/ | ||
1683 | static void ibmvfc_bsg_timeout_done(struct ibmvfc_event *evt) | ||
1684 | { | ||
1685 | struct ibmvfc_host *vhost = evt->vhost; | ||
1686 | |||
1687 | ibmvfc_free_event(evt); | ||
1688 | vhost->aborting_passthru = 0; | ||
1689 | dev_info(vhost->dev, "Passthru command cancelled\n"); | ||
1690 | } | ||
1691 | |||
1692 | /** | ||
1693 | * ibmvfc_bsg_timeout - Handle a BSG timeout | ||
1694 | * @job: struct fc_bsg_job that timed out | ||
1695 | * | ||
1696 | * Returns: | ||
1697 | * 0 on success / other on failure | ||
1698 | **/ | ||
1699 | static int ibmvfc_bsg_timeout(struct fc_bsg_job *job) | ||
1700 | { | ||
1701 | struct ibmvfc_host *vhost = shost_priv(job->shost); | ||
1702 | unsigned long port_id = (unsigned long)job->dd_data; | ||
1703 | struct ibmvfc_event *evt; | ||
1704 | struct ibmvfc_tmf *tmf; | ||
1705 | unsigned long flags; | ||
1706 | int rc; | ||
1707 | |||
1708 | ENTER; | ||
1709 | spin_lock_irqsave(vhost->host->host_lock, flags); | ||
1710 | if (vhost->aborting_passthru || vhost->state != IBMVFC_ACTIVE) { | ||
1711 | __ibmvfc_reset_host(vhost); | ||
1712 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
1713 | return 0; | ||
1714 | } | ||
1715 | |||
1716 | vhost->aborting_passthru = 1; | ||
1717 | evt = ibmvfc_get_event(vhost); | ||
1718 | ibmvfc_init_event(evt, ibmvfc_bsg_timeout_done, IBMVFC_MAD_FORMAT); | ||
1719 | |||
1720 | tmf = &evt->iu.tmf; | ||
1721 | memset(tmf, 0, sizeof(*tmf)); | ||
1722 | tmf->common.version = 1; | ||
1723 | tmf->common.opcode = IBMVFC_TMF_MAD; | ||
1724 | tmf->common.length = sizeof(*tmf); | ||
1725 | tmf->scsi_id = port_id; | ||
1726 | tmf->cancel_key = IBMVFC_PASSTHRU_CANCEL_KEY; | ||
1727 | tmf->my_cancel_key = IBMVFC_INTERNAL_CANCEL_KEY; | ||
1728 | rc = ibmvfc_send_event(evt, vhost, default_timeout); | ||
1729 | |||
1730 | if (rc != 0) { | ||
1731 | vhost->aborting_passthru = 0; | ||
1732 | dev_err(vhost->dev, "Failed to send cancel event. rc=%d\n", rc); | ||
1733 | rc = -EIO; | ||
1734 | } else | ||
1735 | dev_info(vhost->dev, "Cancelling passthru command to port id 0x%lx\n", | ||
1736 | port_id); | ||
1737 | |||
1738 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
1739 | |||
1740 | LEAVE; | ||
1741 | return rc; | ||
1742 | } | ||
1743 | |||
1744 | /** | ||
1745 | * ibmvfc_bsg_plogi - PLOGI into a target to handle a BSG command | ||
1746 | * @vhost: struct ibmvfc_host to send command | ||
1747 | * @port_id: port ID to send command | ||
1748 | * | ||
1749 | * Returns: | ||
1750 | * 0 on success / other on failure | ||
1751 | **/ | ||
1752 | static int ibmvfc_bsg_plogi(struct ibmvfc_host *vhost, unsigned int port_id) | ||
1753 | { | ||
1754 | struct ibmvfc_port_login *plogi; | ||
1755 | struct ibmvfc_target *tgt; | ||
1756 | struct ibmvfc_event *evt; | ||
1757 | union ibmvfc_iu rsp_iu; | ||
1758 | unsigned long flags; | ||
1759 | int rc = 0, issue_login = 1; | ||
1760 | |||
1761 | ENTER; | ||
1762 | spin_lock_irqsave(vhost->host->host_lock, flags); | ||
1763 | list_for_each_entry(tgt, &vhost->targets, queue) { | ||
1764 | if (tgt->scsi_id == port_id) { | ||
1765 | issue_login = 0; | ||
1766 | break; | ||
1767 | } | ||
1768 | } | ||
1769 | |||
1770 | if (!issue_login) | ||
1771 | goto unlock_out; | ||
1772 | if (unlikely((rc = ibmvfc_host_chkready(vhost)))) | ||
1773 | goto unlock_out; | ||
1774 | |||
1775 | evt = ibmvfc_get_event(vhost); | ||
1776 | ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT); | ||
1777 | plogi = &evt->iu.plogi; | ||
1778 | memset(plogi, 0, sizeof(*plogi)); | ||
1779 | plogi->common.version = 1; | ||
1780 | plogi->common.opcode = IBMVFC_PORT_LOGIN; | ||
1781 | plogi->common.length = sizeof(*plogi); | ||
1782 | plogi->scsi_id = port_id; | ||
1783 | evt->sync_iu = &rsp_iu; | ||
1784 | init_completion(&evt->comp); | ||
1785 | |||
1786 | rc = ibmvfc_send_event(evt, vhost, default_timeout); | ||
1787 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
1788 | |||
1789 | if (rc) | ||
1790 | return -EIO; | ||
1791 | |||
1792 | wait_for_completion(&evt->comp); | ||
1793 | |||
1794 | if (rsp_iu.plogi.common.status) | ||
1795 | rc = -EIO; | ||
1796 | |||
1797 | spin_lock_irqsave(vhost->host->host_lock, flags); | ||
1798 | ibmvfc_free_event(evt); | ||
1799 | unlock_out: | ||
1800 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
1801 | LEAVE; | ||
1802 | return rc; | ||
1803 | } | ||
1804 | |||
1805 | /** | ||
1806 | * ibmvfc_bsg_request - Handle a BSG request | ||
1807 | * @job: struct fc_bsg_job to be executed | ||
1808 | * | ||
1809 | * Returns: | ||
1810 | * 0 on success / other on failure | ||
1811 | **/ | ||
1812 | static int ibmvfc_bsg_request(struct fc_bsg_job *job) | ||
1813 | { | ||
1814 | struct ibmvfc_host *vhost = shost_priv(job->shost); | ||
1815 | struct fc_rport *rport = job->rport; | ||
1816 | struct ibmvfc_passthru_mad *mad; | ||
1817 | struct ibmvfc_event *evt; | ||
1818 | union ibmvfc_iu rsp_iu; | ||
1819 | unsigned long flags, port_id = -1; | ||
1820 | unsigned int code = job->request->msgcode; | ||
1821 | int rc = 0, req_seg, rsp_seg, issue_login = 0; | ||
1822 | u32 fc_flags, rsp_len; | ||
1823 | |||
1824 | ENTER; | ||
1825 | job->reply->reply_payload_rcv_len = 0; | ||
1826 | if (rport) | ||
1827 | port_id = rport->port_id; | ||
1828 | |||
1829 | switch (code) { | ||
1830 | case FC_BSG_HST_ELS_NOLOGIN: | ||
1831 | port_id = (job->request->rqst_data.h_els.port_id[0] << 16) | | ||
1832 | (job->request->rqst_data.h_els.port_id[1] << 8) | | ||
1833 | job->request->rqst_data.h_els.port_id[2]; | ||
1834 | case FC_BSG_RPT_ELS: | ||
1835 | fc_flags = IBMVFC_FC_ELS; | ||
1836 | break; | ||
1837 | case FC_BSG_HST_CT: | ||
1838 | issue_login = 1; | ||
1839 | port_id = (job->request->rqst_data.h_ct.port_id[0] << 16) | | ||
1840 | (job->request->rqst_data.h_ct.port_id[1] << 8) | | ||
1841 | job->request->rqst_data.h_ct.port_id[2]; | ||
1842 | case FC_BSG_RPT_CT: | ||
1843 | fc_flags = IBMVFC_FC_CT_IU; | ||
1844 | break; | ||
1845 | default: | ||
1846 | return -ENOTSUPP; | ||
1847 | }; | ||
1848 | |||
1849 | if (port_id == -1) | ||
1850 | return -EINVAL; | ||
1851 | if (!mutex_trylock(&vhost->passthru_mutex)) | ||
1852 | return -EBUSY; | ||
1853 | |||
1854 | job->dd_data = (void *)port_id; | ||
1855 | req_seg = dma_map_sg(vhost->dev, job->request_payload.sg_list, | ||
1856 | job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
1857 | |||
1858 | if (!req_seg) { | ||
1859 | mutex_unlock(&vhost->passthru_mutex); | ||
1860 | return -ENOMEM; | ||
1861 | } | ||
1862 | |||
1863 | rsp_seg = dma_map_sg(vhost->dev, job->reply_payload.sg_list, | ||
1864 | job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
1865 | |||
1866 | if (!rsp_seg) { | ||
1867 | dma_unmap_sg(vhost->dev, job->request_payload.sg_list, | ||
1868 | job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
1869 | mutex_unlock(&vhost->passthru_mutex); | ||
1870 | return -ENOMEM; | ||
1871 | } | ||
1872 | |||
1873 | if (req_seg > 1 || rsp_seg > 1) { | ||
1874 | rc = -EINVAL; | ||
1875 | goto out; | ||
1876 | } | ||
1877 | |||
1878 | if (issue_login) | ||
1879 | rc = ibmvfc_bsg_plogi(vhost, port_id); | ||
1880 | |||
1881 | spin_lock_irqsave(vhost->host->host_lock, flags); | ||
1882 | |||
1883 | if (unlikely(rc || (rport && (rc = fc_remote_port_chkready(rport)))) || | ||
1884 | unlikely((rc = ibmvfc_host_chkready(vhost)))) { | ||
1885 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
1886 | goto out; | ||
1887 | } | ||
1888 | |||
1889 | evt = ibmvfc_get_event(vhost); | ||
1890 | ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT); | ||
1891 | mad = &evt->iu.passthru; | ||
1892 | |||
1893 | memset(mad, 0, sizeof(*mad)); | ||
1894 | mad->common.version = 1; | ||
1895 | mad->common.opcode = IBMVFC_PASSTHRU; | ||
1896 | mad->common.length = sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu); | ||
1897 | |||
1898 | mad->cmd_ioba.va = (u64)evt->crq.ioba + | ||
1899 | offsetof(struct ibmvfc_passthru_mad, iu); | ||
1900 | mad->cmd_ioba.len = sizeof(mad->iu); | ||
1901 | |||
1902 | mad->iu.cmd_len = job->request_payload.payload_len; | ||
1903 | mad->iu.rsp_len = job->reply_payload.payload_len; | ||
1904 | mad->iu.flags = fc_flags; | ||
1905 | mad->iu.cancel_key = IBMVFC_PASSTHRU_CANCEL_KEY; | ||
1906 | |||
1907 | mad->iu.cmd.va = sg_dma_address(job->request_payload.sg_list); | ||
1908 | mad->iu.cmd.len = sg_dma_len(job->request_payload.sg_list); | ||
1909 | mad->iu.rsp.va = sg_dma_address(job->reply_payload.sg_list); | ||
1910 | mad->iu.rsp.len = sg_dma_len(job->reply_payload.sg_list); | ||
1911 | mad->iu.scsi_id = port_id; | ||
1912 | mad->iu.tag = (u64)evt; | ||
1913 | rsp_len = mad->iu.rsp.len; | ||
1914 | |||
1915 | evt->sync_iu = &rsp_iu; | ||
1916 | init_completion(&evt->comp); | ||
1917 | rc = ibmvfc_send_event(evt, vhost, 0); | ||
1918 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
1919 | |||
1920 | if (rc) { | ||
1921 | rc = -EIO; | ||
1922 | goto out; | ||
1923 | } | ||
1924 | |||
1925 | wait_for_completion(&evt->comp); | ||
1926 | |||
1927 | if (rsp_iu.passthru.common.status) | ||
1928 | rc = -EIO; | ||
1929 | else | ||
1930 | job->reply->reply_payload_rcv_len = rsp_len; | ||
1931 | |||
1932 | spin_lock_irqsave(vhost->host->host_lock, flags); | ||
1933 | ibmvfc_free_event(evt); | ||
1934 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
1935 | job->reply->result = rc; | ||
1936 | job->job_done(job); | ||
1937 | rc = 0; | ||
1938 | out: | ||
1939 | dma_unmap_sg(vhost->dev, job->request_payload.sg_list, | ||
1940 | job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
1941 | dma_unmap_sg(vhost->dev, job->reply_payload.sg_list, | ||
1942 | job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
1943 | mutex_unlock(&vhost->passthru_mutex); | ||
1944 | LEAVE; | ||
1945 | return rc; | ||
1946 | } | ||
1947 | |||
1948 | /** | ||
1681 | * ibmvfc_reset_device - Reset the device with the specified reset type | 1949 | * ibmvfc_reset_device - Reset the device with the specified reset type |
1682 | * @sdev: scsi device to reset | 1950 | * @sdev: scsi device to reset |
1683 | * @type: reset type | 1951 | * @type: reset type |
@@ -1731,7 +1999,10 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) | |||
1731 | sdev_printk(KERN_INFO, sdev, "Resetting %s\n", desc); | 1999 | sdev_printk(KERN_INFO, sdev, "Resetting %s\n", desc); |
1732 | wait_for_completion(&evt->comp); | 2000 | wait_for_completion(&evt->comp); |
1733 | 2001 | ||
1734 | if (rsp_iu.cmd.status) { | 2002 | if (rsp_iu.cmd.status) |
2003 | rsp_code = ibmvfc_get_err_result(&rsp_iu.cmd); | ||
2004 | |||
2005 | if (rsp_code) { | ||
1735 | if (fc_rsp->flags & FCP_RSP_LEN_VALID) | 2006 | if (fc_rsp->flags & FCP_RSP_LEN_VALID) |
1736 | rsp_code = fc_rsp->data.info.rsp_code; | 2007 | rsp_code = fc_rsp->data.info.rsp_code; |
1737 | 2008 | ||
@@ -1820,7 +2091,10 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) | |||
1820 | sdev_printk(KERN_INFO, sdev, "Aborting outstanding commands\n"); | 2091 | sdev_printk(KERN_INFO, sdev, "Aborting outstanding commands\n"); |
1821 | wait_for_completion(&evt->comp); | 2092 | wait_for_completion(&evt->comp); |
1822 | 2093 | ||
1823 | if (rsp_iu.cmd.status) { | 2094 | if (rsp_iu.cmd.status) |
2095 | rsp_code = ibmvfc_get_err_result(&rsp_iu.cmd); | ||
2096 | |||
2097 | if (rsp_code) { | ||
1824 | if (fc_rsp->flags & FCP_RSP_LEN_VALID) | 2098 | if (fc_rsp->flags & FCP_RSP_LEN_VALID) |
1825 | rsp_code = fc_rsp->data.info.rsp_code; | 2099 | rsp_code = fc_rsp->data.info.rsp_code; |
1826 | 2100 | ||
@@ -2061,12 +2335,24 @@ static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
2061 | } | 2335 | } |
2062 | 2336 | ||
2063 | /** | 2337 | /** |
2064 | * ibmvfc_dev_cancel_all - Device iterated cancel all function | 2338 | * ibmvfc_dev_cancel_all_abts - Device iterated cancel all function |
2065 | * @sdev: scsi device struct | 2339 | * @sdev: scsi device struct |
2066 | * @data: return code | 2340 | * @data: return code |
2067 | * | 2341 | * |
2068 | **/ | 2342 | **/ |
2069 | static void ibmvfc_dev_cancel_all(struct scsi_device *sdev, void *data) | 2343 | static void ibmvfc_dev_cancel_all_abts(struct scsi_device *sdev, void *data) |
2344 | { | ||
2345 | unsigned long *rc = data; | ||
2346 | *rc |= ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); | ||
2347 | } | ||
2348 | |||
2349 | /** | ||
2350 | * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function | ||
2351 | * @sdev: scsi device struct | ||
2352 | * @data: return code | ||
2353 | * | ||
2354 | **/ | ||
2355 | static void ibmvfc_dev_cancel_all_reset(struct scsi_device *sdev, void *data) | ||
2070 | { | 2356 | { |
2071 | unsigned long *rc = data; | 2357 | unsigned long *rc = data; |
2072 | *rc |= ibmvfc_cancel_all(sdev, IBMVFC_TMF_TGT_RESET); | 2358 | *rc |= ibmvfc_cancel_all(sdev, IBMVFC_TMF_TGT_RESET); |
@@ -2102,7 +2388,7 @@ static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd) | |||
2102 | 2388 | ||
2103 | ENTER; | 2389 | ENTER; |
2104 | ibmvfc_wait_while_resetting(vhost); | 2390 | ibmvfc_wait_while_resetting(vhost); |
2105 | starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all); | 2391 | starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_reset); |
2106 | reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target"); | 2392 | reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target"); |
2107 | 2393 | ||
2108 | if (!cancel_rc && !reset_rc) | 2394 | if (!cancel_rc && !reset_rc) |
@@ -2144,7 +2430,7 @@ static void ibmvfc_terminate_rport_io(struct fc_rport *rport) | |||
2144 | int rc = FAILED; | 2430 | int rc = FAILED; |
2145 | 2431 | ||
2146 | ENTER; | 2432 | ENTER; |
2147 | starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all); | 2433 | starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_abts); |
2148 | starget_for_each_device(starget, &abort_rc, ibmvfc_dev_abort_all); | 2434 | starget_for_each_device(starget, &abort_rc, ibmvfc_dev_abort_all); |
2149 | 2435 | ||
2150 | if (!cancel_rc && !abort_rc) | 2436 | if (!cancel_rc && !abort_rc) |
@@ -2297,13 +2583,13 @@ static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost) | |||
2297 | /* Send back a response */ | 2583 | /* Send back a response */ |
2298 | rc = ibmvfc_send_crq_init_complete(vhost); | 2584 | rc = ibmvfc_send_crq_init_complete(vhost); |
2299 | if (rc == 0) | 2585 | if (rc == 0) |
2300 | ibmvfc_init_host(vhost, 0); | 2586 | ibmvfc_init_host(vhost); |
2301 | else | 2587 | else |
2302 | dev_err(vhost->dev, "Unable to send init rsp. rc=%ld\n", rc); | 2588 | dev_err(vhost->dev, "Unable to send init rsp. rc=%ld\n", rc); |
2303 | break; | 2589 | break; |
2304 | case IBMVFC_CRQ_INIT_COMPLETE: | 2590 | case IBMVFC_CRQ_INIT_COMPLETE: |
2305 | dev_info(vhost->dev, "Partner initialization complete\n"); | 2591 | dev_info(vhost->dev, "Partner initialization complete\n"); |
2306 | ibmvfc_init_host(vhost, 0); | 2592 | ibmvfc_init_host(vhost); |
2307 | break; | 2593 | break; |
2308 | default: | 2594 | default: |
2309 | dev_err(vhost->dev, "Unknown crq message type: %d\n", crq->format); | 2595 | dev_err(vhost->dev, "Unknown crq message type: %d\n", crq->format); |
@@ -2478,12 +2764,17 @@ static int ibmvfc_slave_configure(struct scsi_device *sdev) | |||
2478 | * ibmvfc_change_queue_depth - Change the device's queue depth | 2764 | * ibmvfc_change_queue_depth - Change the device's queue depth |
2479 | * @sdev: scsi device struct | 2765 | * @sdev: scsi device struct |
2480 | * @qdepth: depth to set | 2766 | * @qdepth: depth to set |
2767 | * @reason: calling context | ||
2481 | * | 2768 | * |
2482 | * Return value: | 2769 | * Return value: |
2483 | * actual depth set | 2770 | * actual depth set |
2484 | **/ | 2771 | **/ |
2485 | static int ibmvfc_change_queue_depth(struct scsi_device *sdev, int qdepth) | 2772 | static int ibmvfc_change_queue_depth(struct scsi_device *sdev, int qdepth, |
2773 | int reason) | ||
2486 | { | 2774 | { |
2775 | if (reason != SCSI_QDEPTH_DEFAULT) | ||
2776 | return -EOPNOTSUPP; | ||
2777 | |||
2487 | if (qdepth > IBMVFC_MAX_CMDS_PER_LUN) | 2778 | if (qdepth > IBMVFC_MAX_CMDS_PER_LUN) |
2488 | qdepth = IBMVFC_MAX_CMDS_PER_LUN; | 2779 | qdepth = IBMVFC_MAX_CMDS_PER_LUN; |
2489 | 2780 | ||
@@ -3725,7 +4016,7 @@ static void ibmvfc_npiv_logout_done(struct ibmvfc_event *evt) | |||
3725 | case IBMVFC_MAD_SUCCESS: | 4016 | case IBMVFC_MAD_SUCCESS: |
3726 | if (list_empty(&vhost->sent) && | 4017 | if (list_empty(&vhost->sent) && |
3727 | vhost->action == IBMVFC_HOST_ACTION_LOGO_WAIT) { | 4018 | vhost->action == IBMVFC_HOST_ACTION_LOGO_WAIT) { |
3728 | ibmvfc_init_host(vhost, 0); | 4019 | ibmvfc_init_host(vhost); |
3729 | return; | 4020 | return; |
3730 | } | 4021 | } |
3731 | break; | 4022 | break; |
@@ -3903,6 +4194,8 @@ static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt) | |||
3903 | rport->supported_classes |= FC_COS_CLASS2; | 4194 | rport->supported_classes |= FC_COS_CLASS2; |
3904 | if (tgt->service_parms.class3_parms[0] & 0x80000000) | 4195 | if (tgt->service_parms.class3_parms[0] & 0x80000000) |
3905 | rport->supported_classes |= FC_COS_CLASS3; | 4196 | rport->supported_classes |= FC_COS_CLASS3; |
4197 | if (rport->rqst_q) | ||
4198 | blk_queue_max_hw_segments(rport->rqst_q, 1); | ||
3906 | } else | 4199 | } else |
3907 | tgt_dbg(tgt, "rport add failed\n"); | 4200 | tgt_dbg(tgt, "rport add failed\n"); |
3908 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | 4201 | spin_unlock_irqrestore(vhost->host->host_lock, flags); |
@@ -4342,6 +4635,7 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
4342 | init_waitqueue_head(&vhost->work_wait_q); | 4635 | init_waitqueue_head(&vhost->work_wait_q); |
4343 | init_waitqueue_head(&vhost->init_wait_q); | 4636 | init_waitqueue_head(&vhost->init_wait_q); |
4344 | INIT_WORK(&vhost->rport_add_work_q, ibmvfc_rport_add_thread); | 4637 | INIT_WORK(&vhost->rport_add_work_q, ibmvfc_rport_add_thread); |
4638 | mutex_init(&vhost->passthru_mutex); | ||
4345 | 4639 | ||
4346 | if ((rc = ibmvfc_alloc_mem(vhost))) | 4640 | if ((rc = ibmvfc_alloc_mem(vhost))) |
4347 | goto free_scsi_host; | 4641 | goto free_scsi_host; |
@@ -4374,6 +4668,8 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
4374 | goto remove_shost; | 4668 | goto remove_shost; |
4375 | } | 4669 | } |
4376 | 4670 | ||
4671 | if (shost_to_fc_host(shost)->rqst_q) | ||
4672 | blk_queue_max_hw_segments(shost_to_fc_host(shost)->rqst_q, 1); | ||
4377 | dev_set_drvdata(dev, vhost); | 4673 | dev_set_drvdata(dev, vhost); |
4378 | spin_lock(&ibmvfc_driver_lock); | 4674 | spin_lock(&ibmvfc_driver_lock); |
4379 | list_add_tail(&vhost->queue, &ibmvfc_head); | 4675 | list_add_tail(&vhost->queue, &ibmvfc_head); |
@@ -4414,7 +4710,11 @@ static int ibmvfc_remove(struct vio_dev *vdev) | |||
4414 | 4710 | ||
4415 | ENTER; | 4711 | ENTER; |
4416 | ibmvfc_remove_trace_file(&vhost->host->shost_dev.kobj, &ibmvfc_trace_attr); | 4712 | ibmvfc_remove_trace_file(&vhost->host->shost_dev.kobj, &ibmvfc_trace_attr); |
4713 | |||
4714 | spin_lock_irqsave(vhost->host->host_lock, flags); | ||
4417 | ibmvfc_link_down(vhost, IBMVFC_HOST_OFFLINE); | 4715 | ibmvfc_link_down(vhost, IBMVFC_HOST_OFFLINE); |
4716 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
4717 | |||
4418 | ibmvfc_wait_while_resetting(vhost); | 4718 | ibmvfc_wait_while_resetting(vhost); |
4419 | ibmvfc_release_crq_queue(vhost); | 4719 | ibmvfc_release_crq_queue(vhost); |
4420 | kthread_stop(vhost->work_thread); | 4720 | kthread_stop(vhost->work_thread); |
@@ -4498,6 +4798,9 @@ static struct fc_function_template ibmvfc_transport_functions = { | |||
4498 | 4798 | ||
4499 | .get_starget_port_id = ibmvfc_get_starget_port_id, | 4799 | .get_starget_port_id = ibmvfc_get_starget_port_id, |
4500 | .show_starget_port_id = 1, | 4800 | .show_starget_port_id = 1, |
4801 | |||
4802 | .bsg_request = ibmvfc_bsg_request, | ||
4803 | .bsg_timeout = ibmvfc_bsg_timeout, | ||
4501 | }; | 4804 | }; |
4502 | 4805 | ||
4503 | /** | 4806 | /** |