diff options
Diffstat (limited to 'drivers/scsi/iscsi_tcp.c')
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 102 |
1 files changed, 57 insertions, 45 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index aecadbdce9df..8cdcaf33fb4e 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
@@ -64,6 +64,10 @@ MODULE_LICENSE("GPL"); | |||
64 | #define BUG_ON(expr) | 64 | #define BUG_ON(expr) |
65 | #endif | 65 | #endif |
66 | 66 | ||
67 | static struct scsi_transport_template *iscsi_tcp_scsi_transport; | ||
68 | static struct scsi_host_template iscsi_sht; | ||
69 | static struct iscsi_transport iscsi_tcp_transport; | ||
70 | |||
67 | static unsigned int iscsi_max_lun = 512; | 71 | static unsigned int iscsi_max_lun = 512; |
68 | module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO); | 72 | module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO); |
69 | 73 | ||
@@ -1623,6 +1627,8 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, | |||
1623 | struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, | 1627 | struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, |
1624 | int is_leading) | 1628 | int is_leading) |
1625 | { | 1629 | { |
1630 | struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); | ||
1631 | struct iscsi_host *ihost = shost_priv(shost); | ||
1626 | struct iscsi_conn *conn = cls_conn->dd_data; | 1632 | struct iscsi_conn *conn = cls_conn->dd_data; |
1627 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 1633 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
1628 | struct sock *sk; | 1634 | struct sock *sk; |
@@ -1646,8 +1652,8 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, | |||
1646 | if (err) | 1652 | if (err) |
1647 | goto free_socket; | 1653 | goto free_socket; |
1648 | 1654 | ||
1649 | err = iscsi_tcp_get_addr(conn, sock, conn->local_address, | 1655 | err = iscsi_tcp_get_addr(conn, sock, ihost->local_address, |
1650 | &conn->local_port, kernel_getsockname); | 1656 | &ihost->local_port, kernel_getsockname); |
1651 | if (err) | 1657 | if (err) |
1652 | goto free_socket; | 1658 | goto free_socket; |
1653 | 1659 | ||
@@ -1821,29 +1827,6 @@ iscsi_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn, | |||
1821 | return len; | 1827 | return len; |
1822 | } | 1828 | } |
1823 | 1829 | ||
1824 | static int | ||
1825 | iscsi_tcp_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param, | ||
1826 | char *buf) | ||
1827 | { | ||
1828 | struct iscsi_session *session = iscsi_hostdata(shost->hostdata); | ||
1829 | int len; | ||
1830 | |||
1831 | switch (param) { | ||
1832 | case ISCSI_HOST_PARAM_IPADDRESS: | ||
1833 | spin_lock_bh(&session->lock); | ||
1834 | if (!session->leadconn) | ||
1835 | len = -ENODEV; | ||
1836 | else | ||
1837 | len = sprintf(buf, "%s\n", | ||
1838 | session->leadconn->local_address); | ||
1839 | spin_unlock_bh(&session->lock); | ||
1840 | break; | ||
1841 | default: | ||
1842 | return iscsi_host_get_param(shost, param, buf); | ||
1843 | } | ||
1844 | return len; | ||
1845 | } | ||
1846 | |||
1847 | static void | 1830 | static void |
1848 | iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) | 1831 | iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) |
1849 | { | 1832 | { |
@@ -1869,26 +1852,44 @@ iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) | |||
1869 | } | 1852 | } |
1870 | 1853 | ||
1871 | static struct iscsi_cls_session * | 1854 | static struct iscsi_cls_session * |
1872 | iscsi_tcp_session_create(struct iscsi_transport *iscsit, | 1855 | iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max, |
1873 | struct scsi_transport_template *scsit, | ||
1874 | struct Scsi_Host *shost, uint16_t cmds_max, | ||
1875 | uint16_t qdepth, uint32_t initial_cmdsn, | 1856 | uint16_t qdepth, uint32_t initial_cmdsn, |
1876 | uint32_t *hostno) | 1857 | uint32_t *hostno) |
1877 | { | 1858 | { |
1878 | struct iscsi_cls_session *cls_session; | 1859 | struct iscsi_cls_session *cls_session; |
1879 | struct iscsi_session *session; | 1860 | struct iscsi_session *session; |
1880 | uint32_t hn; | ||
1881 | int cmd_i; | 1861 | int cmd_i; |
1882 | 1862 | ||
1883 | cls_session = iscsi_session_setup(iscsit, scsit, cmds_max, qdepth, | 1863 | if (shost) { |
1884 | sizeof(struct iscsi_tcp_cmd_task), | 1864 | printk(KERN_ERR "iscsi_tcp: invalid shost %d.\n", |
1885 | sizeof(struct iscsi_tcp_mgmt_task), | 1865 | shost->host_no); |
1886 | initial_cmdsn, &hn); | 1866 | return NULL; |
1887 | if (!cls_session) | 1867 | } |
1868 | |||
1869 | shost = scsi_host_alloc(&iscsi_sht, sizeof(struct iscsi_host)); | ||
1870 | if (!shost) | ||
1888 | return NULL; | 1871 | return NULL; |
1889 | *hostno = hn; | 1872 | shost->transportt = iscsi_tcp_scsi_transport; |
1873 | shost->max_lun = iscsi_max_lun; | ||
1874 | shost->max_id = 0; | ||
1875 | shost->max_channel = 0; | ||
1876 | shost->max_cmd_len = 16; | ||
1877 | |||
1878 | iscsi_host_setup(shost, qdepth); | ||
1879 | |||
1880 | if (scsi_add_host(shost, NULL)) | ||
1881 | goto free_host; | ||
1882 | *hostno = shost->host_no; | ||
1883 | |||
1884 | cls_session = iscsi_session_setup(&iscsi_tcp_transport, shost, cmds_max, | ||
1885 | sizeof(struct iscsi_tcp_cmd_task), | ||
1886 | sizeof(struct iscsi_tcp_mgmt_task), | ||
1887 | initial_cmdsn); | ||
1888 | if (!cls_session) | ||
1889 | goto remove_host; | ||
1890 | session = cls_session->dd_data; | ||
1890 | 1891 | ||
1891 | session = class_to_transport_session(cls_session); | 1892 | shost->can_queue = session->cmds_max; |
1892 | for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { | 1893 | for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { |
1893 | struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; | 1894 | struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; |
1894 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1895 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
@@ -1904,20 +1905,30 @@ iscsi_tcp_session_create(struct iscsi_transport *iscsit, | |||
1904 | mtask->hdr = (struct iscsi_hdr *) &tcp_mtask->hdr; | 1905 | mtask->hdr = (struct iscsi_hdr *) &tcp_mtask->hdr; |
1905 | } | 1906 | } |
1906 | 1907 | ||
1907 | if (iscsi_r2tpool_alloc(class_to_transport_session(cls_session))) | 1908 | if (iscsi_r2tpool_alloc(session)) |
1908 | goto r2tpool_alloc_fail; | 1909 | goto remove_session; |
1909 | |||
1910 | return cls_session; | 1910 | return cls_session; |
1911 | 1911 | ||
1912 | r2tpool_alloc_fail: | 1912 | remove_session: |
1913 | iscsi_session_teardown(cls_session); | 1913 | iscsi_session_teardown(cls_session); |
1914 | remove_host: | ||
1915 | scsi_remove_host(shost); | ||
1916 | free_host: | ||
1917 | iscsi_host_teardown(shost); | ||
1918 | scsi_host_put(shost); | ||
1914 | return NULL; | 1919 | return NULL; |
1915 | } | 1920 | } |
1916 | 1921 | ||
1917 | static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session) | 1922 | static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session) |
1918 | { | 1923 | { |
1919 | iscsi_r2tpool_free(class_to_transport_session(cls_session)); | 1924 | struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); |
1925 | |||
1926 | iscsi_r2tpool_free(cls_session->dd_data); | ||
1920 | iscsi_session_teardown(cls_session); | 1927 | iscsi_session_teardown(cls_session); |
1928 | |||
1929 | scsi_remove_host(shost); | ||
1930 | iscsi_host_teardown(shost); | ||
1931 | scsi_host_put(shost); | ||
1921 | } | 1932 | } |
1922 | 1933 | ||
1923 | static int iscsi_tcp_slave_configure(struct scsi_device *sdev) | 1934 | static int iscsi_tcp_slave_configure(struct scsi_device *sdev) |
@@ -1976,8 +1987,8 @@ static struct iscsi_transport iscsi_tcp_transport = { | |||
1976 | .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | | 1987 | .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | |
1977 | ISCSI_HOST_INITIATOR_NAME | | 1988 | ISCSI_HOST_INITIATOR_NAME | |
1978 | ISCSI_HOST_NETDEV_NAME, | 1989 | ISCSI_HOST_NETDEV_NAME, |
1979 | .host_template = &iscsi_sht, | ||
1980 | .conndata_size = sizeof(struct iscsi_conn), | 1990 | .conndata_size = sizeof(struct iscsi_conn), |
1991 | .sessiondata_size = sizeof(struct iscsi_session), | ||
1981 | /* session management */ | 1992 | /* session management */ |
1982 | .create_session = iscsi_tcp_session_create, | 1993 | .create_session = iscsi_tcp_session_create, |
1983 | .destroy_session = iscsi_tcp_session_destroy, | 1994 | .destroy_session = iscsi_tcp_session_destroy, |
@@ -1991,7 +2002,7 @@ static struct iscsi_transport iscsi_tcp_transport = { | |||
1991 | .start_conn = iscsi_conn_start, | 2002 | .start_conn = iscsi_conn_start, |
1992 | .stop_conn = iscsi_tcp_conn_stop, | 2003 | .stop_conn = iscsi_tcp_conn_stop, |
1993 | /* iscsi host params */ | 2004 | /* iscsi host params */ |
1994 | .get_host_param = iscsi_tcp_host_get_param, | 2005 | .get_host_param = iscsi_host_get_param, |
1995 | .set_host_param = iscsi_host_set_param, | 2006 | .set_host_param = iscsi_host_set_param, |
1996 | /* IO */ | 2007 | /* IO */ |
1997 | .send_pdu = iscsi_conn_send_pdu, | 2008 | .send_pdu = iscsi_conn_send_pdu, |
@@ -2013,9 +2024,10 @@ iscsi_tcp_init(void) | |||
2013 | iscsi_max_lun); | 2024 | iscsi_max_lun); |
2014 | return -EINVAL; | 2025 | return -EINVAL; |
2015 | } | 2026 | } |
2016 | iscsi_tcp_transport.max_lun = iscsi_max_lun; | ||
2017 | 2027 | ||
2018 | if (!iscsi_register_transport(&iscsi_tcp_transport)) | 2028 | iscsi_tcp_scsi_transport = iscsi_register_transport( |
2029 | &iscsi_tcp_transport); | ||
2030 | if (!iscsi_tcp_scsi_transport) | ||
2019 | return -ENODEV; | 2031 | return -ENODEV; |
2020 | 2032 | ||
2021 | return 0; | 2033 | return 0; |