aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2008-05-21 16:54:00 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-07-12 09:22:16 -0400
commita4804cd6eb19318ae8d08ea967cfeaaf5c5b68a6 (patch)
treea69acbfdf4e3646ebb7583f0627b7b7952d13b10 /drivers/scsi
parent756135215ec743be6fdce2bdebe8cdb9f8a231f6 (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.c18
-rw-r--r--drivers/scsi/libiscsi.c60
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c20
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,
1912remove_session: 1911remove_session:
1913 iscsi_session_teardown(cls_session); 1912 iscsi_session_teardown(cls_session);
1914remove_host: 1913remove_host:
1915 scsi_remove_host(shost); 1914 iscsi_host_remove(shost);
1916free_host: 1915free_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
1934static int iscsi_tcp_slave_configure(struct scsi_device *sdev) 1930static 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}
1765EXPORT_SYMBOL_GPL(iscsi_pool_free); 1765EXPORT_SYMBOL_GPL(iscsi_pool_free);
1766 1766
1767void 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 */
1775int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev)
1776{
1777 return scsi_add_host(shost, pdev);
1778}
1779EXPORT_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 */
1790struct 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}
1810EXPORT_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 */
1821void 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}
1781EXPORT_SYMBOL_GPL(iscsi_host_setup); 1826EXPORT_SYMBOL_GPL(iscsi_host_remove);
1782 1827
1783void iscsi_host_teardown(struct Scsi_Host *shost) 1828void 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}
1791EXPORT_SYMBOL_GPL(iscsi_host_teardown); 1837EXPORT_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
282static 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
292void 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}
298EXPORT_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);