aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c17
-rw-r--r--drivers/scsi/iscsi_tcp.c18
-rw-r--r--drivers/scsi/libiscsi.c60
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c20
-rw-r--r--include/scsi/libiscsi.h11
-rw-r--r--include/scsi/scsi_transport_iscsi.h4
6 files changed, 99 insertions, 31 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 5a750042e2b2..62e35e503e49 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -371,10 +371,8 @@ static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session)
371{ 371{
372 struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); 372 struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
373 373
374 iscsi_session_teardown(cls_session); 374 iscsi_host_remove(shost);
375 scsi_remove_host(shost); 375 iscsi_host_free(shost);
376 iscsi_host_teardown(shost);
377 scsi_host_put(shost);
378} 376}
379 377
380static struct iscsi_cls_session * 378static struct iscsi_cls_session *
@@ -396,7 +394,7 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
396 return NULL; 394 return NULL;
397 } 395 }
398 396
399 shost = scsi_host_alloc(&iscsi_iser_sht, 0); 397 shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISCSI_MAX_CMD_PER_LUN);
400 if (!shost) 398 if (!shost)
401 return NULL; 399 return NULL;
402 shost->transportt = iscsi_iser_scsi_transport; 400 shost->transportt = iscsi_iser_scsi_transport;
@@ -405,9 +403,7 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
405 shost->max_channel = 0; 403 shost->max_channel = 0;
406 shost->max_cmd_len = 16; 404 shost->max_cmd_len = 16;
407 405
408 iscsi_host_setup(shost, qdepth); 406 if (iscsi_host_add(shost, NULL))
409
410 if (scsi_add_host(shost, NULL))
411 goto free_host; 407 goto free_host;
412 *hostno = shost->host_no; 408 *hostno = shost->host_no;
413 409
@@ -443,10 +439,9 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
443 return cls_session; 439 return cls_session;
444 440
445remove_host: 441remove_host:
446 scsi_remove_host(shost); 442 iscsi_host_remove(shost);
447free_host: 443free_host:
448 iscsi_host_teardown(shost); 444 iscsi_host_free(shost);
449 scsi_host_put(shost);
450 return NULL; 445 return NULL;
451} 446}
452 447
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);
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 8a6271c20935..9a26d715a953 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -32,6 +32,7 @@
32#include <scsi/iscsi_if.h> 32#include <scsi/iscsi_if.h>
33 33
34struct scsi_transport_template; 34struct scsi_transport_template;
35struct scsi_host_template;
35struct scsi_device; 36struct scsi_device;
36struct Scsi_Host; 37struct Scsi_Host;
37struct scsi_cmnd; 38struct scsi_cmnd;
@@ -41,6 +42,7 @@ struct iscsi_cls_session;
41struct iscsi_cls_conn; 42struct iscsi_cls_conn;
42struct iscsi_session; 43struct iscsi_session;
43struct iscsi_nopin; 44struct iscsi_nopin;
45struct device;
44 46
45/* #define DEBUG_SCSI */ 47/* #define DEBUG_SCSI */
46#ifdef DEBUG_SCSI 48#ifdef DEBUG_SCSI
@@ -311,6 +313,8 @@ struct iscsi_host {
311 char local_address[ISCSI_ADDRESS_BUF_LEN]; 313 char local_address[ISCSI_ADDRESS_BUF_LEN];
312}; 314};
313 315
316#define iscsi_host_priv(_shost) \
317 (shost_priv(_shost) + sizeof(struct iscsi_host))
314/* 318/*
315 * scsi host template 319 * scsi host template
316 */ 320 */
@@ -330,8 +334,11 @@ extern int iscsi_host_set_param(struct Scsi_Host *shost,
330 int buflen); 334 int buflen);
331extern int iscsi_host_get_param(struct Scsi_Host *shost, 335extern int iscsi_host_get_param(struct Scsi_Host *shost,
332 enum iscsi_host_param param, char *buf); 336 enum iscsi_host_param param, char *buf);
333extern void iscsi_host_setup(struct Scsi_Host *shost, uint16_t qdepth); 337extern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev);
334extern void iscsi_host_teardown(struct Scsi_Host *shost); 338extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
339 int dd_data_size, uint16_t qdepth);
340extern void iscsi_host_remove(struct Scsi_Host *shost);
341extern void iscsi_host_free(struct Scsi_Host *shost);
335 342
336/* 343/*
337 * session management 344 * session management
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 702eda2904d7..761f62da7cc8 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -207,6 +207,10 @@ struct iscsi_cls_host {
207 char scan_workq_name[KOBJ_NAME_LEN]; 207 char scan_workq_name[KOBJ_NAME_LEN];
208}; 208};
209 209
210extern void iscsi_host_for_each_session(struct Scsi_Host *shost,
211 void (*fn)(struct iscsi_cls_session *));
212
213
210/* 214/*
211 * session and connection functions that can be used by HW iSCSI LLDs 215 * session and connection functions that can be used by HW iSCSI LLDs
212 */ 216 */