aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2008-05-21 16:54:17 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-07-12 09:22:21 -0400
commit3cf7b233ffc45d4fc381221f74d24f10e692c4ea (patch)
treec1bd741628e1e75cf07fa5c47fbdaa9e9f9236ee
parent88dfd340b9dece8fcaa1a2d4c782338926c017f7 (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>
-rw-r--r--drivers/scsi/libiscsi.c49
-rw-r--r--include/scsi/libiscsi.h9
2 files changed, 39 insertions, 19 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 */
1897struct iscsi_cls_session * 1901struct iscsi_cls_session *
1898iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, 1902iscsi_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;
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 21cfb1d5483f..5bf0187e7520 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -52,9 +52,7 @@ struct device;
52#endif 52#endif
53 53
54#define ISCSI_DEF_XMIT_CMDS_MAX 128 /* must be power of 2 */ 54#define ISCSI_DEF_XMIT_CMDS_MAX 128 /* must be power of 2 */
55#define ISCSI_MGMT_CMDS_MAX 16 /* must be power of 2 */ 55#define ISCSI_MGMT_CMDS_MAX 15
56
57#define ISCSI_MGMT_ITT_OFFSET 0xa00
58 56
59#define ISCSI_DEF_CMD_PER_LUN 32 57#define ISCSI_DEF_CMD_PER_LUN 32
60#define ISCSI_MAX_CMD_PER_LUN 128 58#define ISCSI_MAX_CMD_PER_LUN 128
@@ -72,7 +70,10 @@ enum {
72/* Connection suspend "bit" */ 70/* Connection suspend "bit" */
73#define ISCSI_SUSPEND_BIT 1 71#define ISCSI_SUSPEND_BIT 1
74 72
75#define ISCSI_ITT_MASK (0xfff) 73#define ISCSI_ITT_MASK (0x1fff)
74#define ISCSI_TOTAL_CMDS_MAX 4096
75/* this must be a power of two greater than ISCSI_MGMT_CMDS_MAX */
76#define ISCSI_TOTAL_CMDS_MIN 16
76#define ISCSI_AGE_SHIFT 28 77#define ISCSI_AGE_SHIFT 28
77#define ISCSI_AGE_MASK (0xf << ISCSI_AGE_SHIFT) 78#define ISCSI_AGE_MASK (0xf << ISCSI_AGE_SHIFT)
78 79