diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2008-05-21 16:54:17 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-07-12 09:22:21 -0400 |
commit | 3cf7b233ffc45d4fc381221f74d24f10e692c4ea (patch) | |
tree | c1bd741628e1e75cf07fa5c47fbdaa9e9f9236ee /drivers/scsi/libiscsi.c | |
parent | 88dfd340b9dece8fcaa1a2d4c782338926c017f7 (diff) |
[SCSI] libiscsi: fix cmds_max setting
Drivers expect that the cmds_max value they pass to the iscsi layer
is the max scsi commands + mgmt tasks. This patch implements that
and fixes some checks for nr cmd limits.
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 49 |
1 files changed, 34 insertions, 15 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index c1af2aa8e4e0..c723e60f02b0 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -1893,29 +1893,48 @@ EXPORT_SYMBOL_GPL(iscsi_host_free); | |||
1893 | * | 1893 | * |
1894 | * This can be used by software iscsi_transports that allocate | 1894 | * This can be used by software iscsi_transports that allocate |
1895 | * a session per scsi host. | 1895 | * a session per scsi host. |
1896 | * | ||
1897 | * Callers should set cmds_max to the largest total numer (mgmt + scsi) of | ||
1898 | * tasks they support. The iscsi layer reserves ISCSI_MGMT_CMDS_MAX tasks | ||
1899 | * for nop handling and login/logout requests. | ||
1896 | */ | 1900 | */ |
1897 | struct iscsi_cls_session * | 1901 | struct iscsi_cls_session * |
1898 | iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, | 1902 | iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, |
1899 | uint16_t scsi_cmds_max, int cmd_task_size, | 1903 | uint16_t cmds_max, int cmd_task_size, |
1900 | uint32_t initial_cmdsn, unsigned int id) | 1904 | uint32_t initial_cmdsn, unsigned int id) |
1901 | { | 1905 | { |
1902 | struct iscsi_session *session; | 1906 | struct iscsi_session *session; |
1903 | struct iscsi_cls_session *cls_session; | 1907 | struct iscsi_cls_session *cls_session; |
1904 | int cmd_i, cmds_max; | 1908 | int cmd_i, scsi_cmds, total_cmds = cmds_max; |
1905 | |||
1906 | /* | 1909 | /* |
1907 | * The iscsi layer needs some tasks for nop handling and tmfs. | 1910 | * The iscsi layer needs some tasks for nop handling and tmfs, |
1911 | * so the cmds_max must at least be greater than ISCSI_MGMT_CMDS_MAX | ||
1912 | * + 1 command for scsi IO. | ||
1908 | */ | 1913 | */ |
1909 | if (scsi_cmds_max < 1) | 1914 | if (total_cmds < ISCSI_TOTAL_CMDS_MIN) { |
1910 | scsi_cmds_max = ISCSI_MGMT_CMDS_MAX; | 1915 | printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue " |
1911 | if ((scsi_cmds_max + ISCSI_MGMT_CMDS_MAX) >= ISCSI_MGMT_ITT_OFFSET) { | 1916 | "must be a power of two that is at least %d.\n", |
1912 | printk(KERN_ERR "iscsi: invalid can_queue of %d. " | 1917 | total_cmds, ISCSI_TOTAL_CMDS_MIN); |
1913 | "can_queue must be less than %d.\n", | 1918 | return NULL; |
1914 | scsi_cmds_max, | 1919 | } |
1915 | ISCSI_MGMT_ITT_OFFSET - ISCSI_MGMT_CMDS_MAX); | 1920 | |
1916 | scsi_cmds_max = ISCSI_DEF_XMIT_CMDS_MAX; | 1921 | if (total_cmds > ISCSI_TOTAL_CMDS_MAX) { |
1922 | printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue " | ||
1923 | "must be a power of 2 less than or equal to %d.\n", | ||
1924 | cmds_max, ISCSI_TOTAL_CMDS_MAX); | ||
1925 | total_cmds = ISCSI_TOTAL_CMDS_MAX; | ||
1926 | } | ||
1927 | |||
1928 | if (!is_power_of_2(total_cmds)) { | ||
1929 | printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue " | ||
1930 | "must be a power of 2.\n", total_cmds); | ||
1931 | total_cmds = rounddown_pow_of_two(total_cmds); | ||
1932 | if (total_cmds < ISCSI_TOTAL_CMDS_MIN) | ||
1933 | return NULL; | ||
1934 | printk(KERN_INFO "iscsi: Rounding can_queue to %d.\n", | ||
1935 | total_cmds); | ||
1917 | } | 1936 | } |
1918 | cmds_max = roundup_pow_of_two(scsi_cmds_max + ISCSI_MGMT_CMDS_MAX); | 1937 | scsi_cmds = total_cmds - ISCSI_MGMT_CMDS_MAX; |
1919 | 1938 | ||
1920 | cls_session = iscsi_alloc_session(shost, iscsit, | 1939 | cls_session = iscsi_alloc_session(shost, iscsit, |
1921 | sizeof(struct iscsi_session)); | 1940 | sizeof(struct iscsi_session)); |
@@ -1928,8 +1947,8 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, | |||
1928 | session->fast_abort = 1; | 1947 | session->fast_abort = 1; |
1929 | session->lu_reset_timeout = 15; | 1948 | session->lu_reset_timeout = 15; |
1930 | session->abort_timeout = 10; | 1949 | session->abort_timeout = 10; |
1931 | session->scsi_cmds_max = scsi_cmds_max; | 1950 | session->scsi_cmds_max = scsi_cmds; |
1932 | session->cmds_max = cmds_max; | 1951 | session->cmds_max = total_cmds; |
1933 | session->queued_cmdsn = session->cmdsn = initial_cmdsn; | 1952 | session->queued_cmdsn = session->cmdsn = initial_cmdsn; |
1934 | session->exp_cmdsn = initial_cmdsn + 1; | 1953 | session->exp_cmdsn = initial_cmdsn + 1; |
1935 | session->max_cmdsn = initial_cmdsn + 1; | 1954 | session->max_cmdsn = initial_cmdsn + 1; |