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 | |
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>
-rw-r--r-- | drivers/infiniband/ulp/iser/iscsi_iser.c | 17 | ||||
-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 | ||||
-rw-r--r-- | include/scsi/libiscsi.h | 11 | ||||
-rw-r--r-- | include/scsi/scsi_transport_iscsi.h | 4 |
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 | ||
380 | static struct iscsi_cls_session * | 378 | static 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 | ||
445 | remove_host: | 441 | remove_host: |
446 | scsi_remove_host(shost); | 442 | iscsi_host_remove(shost); |
447 | free_host: | 443 | free_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, | |||
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); |
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 | ||
34 | struct scsi_transport_template; | 34 | struct scsi_transport_template; |
35 | struct scsi_host_template; | ||
35 | struct scsi_device; | 36 | struct scsi_device; |
36 | struct Scsi_Host; | 37 | struct Scsi_Host; |
37 | struct scsi_cmnd; | 38 | struct scsi_cmnd; |
@@ -41,6 +42,7 @@ struct iscsi_cls_session; | |||
41 | struct iscsi_cls_conn; | 42 | struct iscsi_cls_conn; |
42 | struct iscsi_session; | 43 | struct iscsi_session; |
43 | struct iscsi_nopin; | 44 | struct iscsi_nopin; |
45 | struct 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); |
331 | extern int iscsi_host_get_param(struct Scsi_Host *shost, | 335 | extern 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); |
333 | extern void iscsi_host_setup(struct Scsi_Host *shost, uint16_t qdepth); | 337 | extern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev); |
334 | extern void iscsi_host_teardown(struct Scsi_Host *shost); | 338 | extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, |
339 | int dd_data_size, uint16_t qdepth); | ||
340 | extern void iscsi_host_remove(struct Scsi_Host *shost); | ||
341 | extern 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 | ||
210 | extern 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 | */ |