diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2008-05-21 16:54:00 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-07-12 09:22:16 -0400 |
commit | a4804cd6eb19318ae8d08ea967cfeaaf5c5b68a6 (patch) | |
tree | a69acbfdf4e3646ebb7583f0627b7b7952d13b10 /drivers/scsi | |
parent | 756135215ec743be6fdce2bdebe8cdb9f8a231f6 (diff) |
[SCSI] iscsi: add iscsi host helpers
This finishes the host/session unbinding, by adding some helpers
to add and remove hosts and the session they manage.
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 18 | ||||
-rw-r--r-- | drivers/scsi/libiscsi.c | 60 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 20 |
3 files changed, 80 insertions, 18 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 8cdcaf33fb4e..e19d92f2d753 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
@@ -1866,7 +1866,7 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max, | |||
1866 | return NULL; | 1866 | return NULL; |
1867 | } | 1867 | } |
1868 | 1868 | ||
1869 | shost = scsi_host_alloc(&iscsi_sht, sizeof(struct iscsi_host)); | 1869 | shost = iscsi_host_alloc(&iscsi_sht, 0, qdepth); |
1870 | if (!shost) | 1870 | if (!shost) |
1871 | return NULL; | 1871 | return NULL; |
1872 | shost->transportt = iscsi_tcp_scsi_transport; | 1872 | shost->transportt = iscsi_tcp_scsi_transport; |
@@ -1874,10 +1874,9 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max, | |||
1874 | shost->max_id = 0; | 1874 | shost->max_id = 0; |
1875 | shost->max_channel = 0; | 1875 | shost->max_channel = 0; |
1876 | shost->max_cmd_len = 16; | 1876 | shost->max_cmd_len = 16; |
1877 | shost->can_queue = cmds_max; | ||
1877 | 1878 | ||
1878 | iscsi_host_setup(shost, qdepth); | 1879 | if (iscsi_host_add(shost, NULL)) |
1879 | |||
1880 | if (scsi_add_host(shost, NULL)) | ||
1881 | goto free_host; | 1880 | goto free_host; |
1882 | *hostno = shost->host_no; | 1881 | *hostno = shost->host_no; |
1883 | 1882 | ||
@@ -1912,10 +1911,9 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max, | |||
1912 | remove_session: | 1911 | remove_session: |
1913 | iscsi_session_teardown(cls_session); | 1912 | iscsi_session_teardown(cls_session); |
1914 | remove_host: | 1913 | remove_host: |
1915 | scsi_remove_host(shost); | 1914 | iscsi_host_remove(shost); |
1916 | free_host: | 1915 | free_host: |
1917 | iscsi_host_teardown(shost); | 1916 | iscsi_host_free(shost); |
1918 | scsi_host_put(shost); | ||
1919 | return NULL; | 1917 | return NULL; |
1920 | } | 1918 | } |
1921 | 1919 | ||
@@ -1924,11 +1922,9 @@ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session) | |||
1924 | struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); | 1922 | struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); |
1925 | 1923 | ||
1926 | iscsi_r2tpool_free(cls_session->dd_data); | 1924 | iscsi_r2tpool_free(cls_session->dd_data); |
1927 | iscsi_session_teardown(cls_session); | ||
1928 | 1925 | ||
1929 | scsi_remove_host(shost); | 1926 | iscsi_host_remove(shost); |
1930 | iscsi_host_teardown(shost); | 1927 | iscsi_host_free(shost); |
1931 | scsi_host_put(shost); | ||
1932 | } | 1928 | } |
1933 | 1929 | ||
1934 | static int iscsi_tcp_slave_configure(struct scsi_device *sdev) | 1930 | static int iscsi_tcp_slave_configure(struct scsi_device *sdev) |
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 64b1dd827366..73c37c04ca66 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -1764,8 +1764,39 @@ void iscsi_pool_free(struct iscsi_pool *q) | |||
1764 | } | 1764 | } |
1765 | EXPORT_SYMBOL_GPL(iscsi_pool_free); | 1765 | EXPORT_SYMBOL_GPL(iscsi_pool_free); |
1766 | 1766 | ||
1767 | void iscsi_host_setup(struct Scsi_Host *shost, uint16_t qdepth) | 1767 | /** |
1768 | * iscsi_host_add - add host to system | ||
1769 | * @shost: scsi host | ||
1770 | * @pdev: parent device | ||
1771 | * | ||
1772 | * This should be called by partial offload and software iscsi drivers | ||
1773 | * to add a host to the system. | ||
1774 | */ | ||
1775 | int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev) | ||
1776 | { | ||
1777 | return scsi_add_host(shost, pdev); | ||
1778 | } | ||
1779 | EXPORT_SYMBOL_GPL(iscsi_host_add); | ||
1780 | |||
1781 | /** | ||
1782 | * iscsi_host_alloc - allocate a host and driver data | ||
1783 | * @sht: scsi host template | ||
1784 | * @dd_data_size: driver host data size | ||
1785 | * @qdepth: default device queue depth | ||
1786 | * | ||
1787 | * This should be called by partial offload and software iscsi drivers. | ||
1788 | * To access the driver specific memory use the iscsi_host_priv() macro. | ||
1789 | */ | ||
1790 | struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, | ||
1791 | int dd_data_size, uint16_t qdepth) | ||
1768 | { | 1792 | { |
1793 | struct Scsi_Host *shost; | ||
1794 | |||
1795 | shost = scsi_host_alloc(sht, sizeof(struct iscsi_host) + dd_data_size); | ||
1796 | if (!shost) | ||
1797 | return NULL; | ||
1798 | shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out; | ||
1799 | |||
1769 | if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) { | 1800 | if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) { |
1770 | if (qdepth != 0) | 1801 | if (qdepth != 0) |
1771 | printk(KERN_ERR "iscsi: invalid queue depth of %d. " | 1802 | printk(KERN_ERR "iscsi: invalid queue depth of %d. " |
@@ -1773,22 +1804,37 @@ void iscsi_host_setup(struct Scsi_Host *shost, uint16_t qdepth) | |||
1773 | qdepth, ISCSI_MAX_CMD_PER_LUN); | 1804 | qdepth, ISCSI_MAX_CMD_PER_LUN); |
1774 | qdepth = ISCSI_DEF_CMD_PER_LUN; | 1805 | qdepth = ISCSI_DEF_CMD_PER_LUN; |
1775 | } | 1806 | } |
1776 | |||
1777 | shost->transportt->create_work_queue = 1; | ||
1778 | shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out; | ||
1779 | shost->cmd_per_lun = qdepth; | 1807 | shost->cmd_per_lun = qdepth; |
1808 | return shost; | ||
1809 | } | ||
1810 | EXPORT_SYMBOL_GPL(iscsi_host_alloc); | ||
1811 | |||
1812 | /** | ||
1813 | * iscsi_host_remove - remove host and sessions | ||
1814 | * @shost: scsi host | ||
1815 | * | ||
1816 | * This will also remove any sessions attached to the host, but if userspace | ||
1817 | * is managing the session at the same time this will break. TODO: add | ||
1818 | * refcounting to the netlink iscsi interface so a rmmod or host hot unplug | ||
1819 | * does not remove the memory from under us. | ||
1820 | */ | ||
1821 | void iscsi_host_remove(struct Scsi_Host *shost) | ||
1822 | { | ||
1823 | iscsi_host_for_each_session(shost, iscsi_session_teardown); | ||
1824 | scsi_remove_host(shost); | ||
1780 | } | 1825 | } |
1781 | EXPORT_SYMBOL_GPL(iscsi_host_setup); | 1826 | EXPORT_SYMBOL_GPL(iscsi_host_remove); |
1782 | 1827 | ||
1783 | void iscsi_host_teardown(struct Scsi_Host *shost) | 1828 | void iscsi_host_free(struct Scsi_Host *shost) |
1784 | { | 1829 | { |
1785 | struct iscsi_host *ihost = shost_priv(shost); | 1830 | struct iscsi_host *ihost = shost_priv(shost); |
1786 | 1831 | ||
1787 | kfree(ihost->netdev); | 1832 | kfree(ihost->netdev); |
1788 | kfree(ihost->hwaddress); | 1833 | kfree(ihost->hwaddress); |
1789 | kfree(ihost->initiatorname); | 1834 | kfree(ihost->initiatorname); |
1835 | scsi_host_put(shost); | ||
1790 | } | 1836 | } |
1791 | EXPORT_SYMBOL_GPL(iscsi_host_teardown); | 1837 | EXPORT_SYMBOL_GPL(iscsi_host_free); |
1792 | 1838 | ||
1793 | /** | 1839 | /** |
1794 | * iscsi_session_setup - create iscsi cls session and host and session | 1840 | * iscsi_session_setup - create iscsi cls session and host and session |
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 9c00a157b485..6fdaa2ee6632 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -279,6 +279,24 @@ static int iscsi_is_session_dev(const struct device *dev) | |||
279 | return dev->release == iscsi_session_release; | 279 | return dev->release == iscsi_session_release; |
280 | } | 280 | } |
281 | 281 | ||
282 | static int iscsi_iter_session_fn(struct device *dev, void *data) | ||
283 | { | ||
284 | void (* fn) (struct iscsi_cls_session *) = data; | ||
285 | |||
286 | if (!iscsi_is_session_dev(dev)) | ||
287 | return 0; | ||
288 | fn(iscsi_dev_to_session(dev)); | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | void iscsi_host_for_each_session(struct Scsi_Host *shost, | ||
293 | void (*fn)(struct iscsi_cls_session *)) | ||
294 | { | ||
295 | device_for_each_child(&shost->shost_gendev, fn, | ||
296 | iscsi_iter_session_fn); | ||
297 | } | ||
298 | EXPORT_SYMBOL_GPL(iscsi_host_for_each_session); | ||
299 | |||
282 | /** | 300 | /** |
283 | * iscsi_scan_finished - helper to report when running scans are done | 301 | * iscsi_scan_finished - helper to report when running scans are done |
284 | * @shost: scsi host | 302 | * @shost: scsi host |
@@ -1599,6 +1617,8 @@ iscsi_register_transport(struct iscsi_transport *tt) | |||
1599 | priv->daemon_pid = -1; | 1617 | priv->daemon_pid = -1; |
1600 | priv->iscsi_transport = tt; | 1618 | priv->iscsi_transport = tt; |
1601 | priv->t.user_scan = iscsi_user_scan; | 1619 | priv->t.user_scan = iscsi_user_scan; |
1620 | if (!(tt->caps & CAP_DATA_PATH_OFFLOAD)) | ||
1621 | priv->t.create_work_queue = 1; | ||
1602 | 1622 | ||
1603 | priv->dev.class = &iscsi_transport_class; | 1623 | priv->dev.class = &iscsi_transport_class; |
1604 | snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%s", tt->name); | 1624 | snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%s", tt->name); |