aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2009-03-05 15:46:03 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-03-13 16:28:37 -0400
commit32ae763e3fce4192cd008956a340353a2e5c3192 (patch)
treeaf13b359c4e54fe60c8eb76c8927b41468dcbe57
parent06d25af4edb60f9e9c7e74d342a6963a32e3392f (diff)
[SCSI] iscsi lib: have lib create work queue for transmitting IO
We were using the shost work queue which ended up being a little akward since all iscsi hosts need a thread for scanning, but only drivers hooked into libiscsi need a workqueue for transmitting. So this patch moves the xmit workqueue to the lib. 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.c2
-rw-r--r--drivers/infiniband/ulp/iser/iser_initiator.c2
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_iscsi.c2
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_pdu.c2
-rw-r--r--drivers/scsi/iscsi_tcp.c4
-rw-r--r--drivers/scsi/libiscsi.c45
-rw-r--r--include/scsi/libiscsi.h7
7 files changed, 48 insertions, 16 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 5f79c0a5faf3..a50cd53e2753 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -404,7 +404,7 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
404 struct Scsi_Host *shost; 404 struct Scsi_Host *shost;
405 struct iser_conn *ib_conn; 405 struct iser_conn *ib_conn;
406 406
407 shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISER_DEF_CMD_PER_LUN); 407 shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISER_DEF_CMD_PER_LUN, 1);
408 if (!shost) 408 if (!shost)
409 return NULL; 409 return NULL;
410 shost->transportt = iscsi_iser_scsi_transport; 410 shost->transportt = iscsi_iser_scsi_transport;
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
index e209cb8dd948..9de640200ad3 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -661,7 +661,7 @@ void iser_snd_completion(struct iser_desc *tx_desc)
661 661
662 if (resume_tx) { 662 if (resume_tx) {
663 iser_dbg("%ld resuming tx\n",jiffies); 663 iser_dbg("%ld resuming tx\n",jiffies);
664 scsi_queue_work(conn->session->host, &conn->xmitwork); 664 iscsi_conn_queue_work(conn);
665 } 665 }
666 666
667 if (tx_desc->type == ISCSI_TX_CONTROL) { 667 if (tx_desc->type == ISCSI_TX_CONTROL) {
diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
index fa2a44f37b36..f6ed9c62efb0 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
@@ -171,7 +171,7 @@ struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic,
171 171
172 shost = iscsi_host_alloc(&cxgb3i_host_template, 172 shost = iscsi_host_alloc(&cxgb3i_host_template,
173 sizeof(struct cxgb3i_hba), 173 sizeof(struct cxgb3i_hba),
174 CXGB3I_SCSI_QDEPTH_DFLT); 174 CXGB3I_SCSI_QDEPTH_DFLT, 1);
175 if (!shost) { 175 if (!shost) {
176 cxgb3i_log_info("iscsi_host_alloc failed.\n"); 176 cxgb3i_log_info("iscsi_host_alloc failed.\n");
177 return NULL; 177 return NULL;
diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.c b/drivers/scsi/cxgb3i/cxgb3i_pdu.c
index 17115c230d65..7eebc9a7cb35 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_pdu.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_pdu.c
@@ -479,7 +479,7 @@ void cxgb3i_conn_tx_open(struct s3_conn *c3cn)
479 cxgb3i_tx_debug("cn 0x%p.\n", c3cn); 479 cxgb3i_tx_debug("cn 0x%p.\n", c3cn);
480 if (conn) { 480 if (conn) {
481 cxgb3i_tx_debug("cn 0x%p, cid %d.\n", c3cn, conn->id); 481 cxgb3i_tx_debug("cn 0x%p, cid %d.\n", c3cn, conn->id);
482 scsi_queue_work(conn->session->host, &conn->xmitwork); 482 iscsi_conn_queue_work(conn);
483 } 483 }
484} 484}
485 485
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 9c2e52792bdc..79a706a94c68 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -166,7 +166,7 @@ static void iscsi_sw_tcp_write_space(struct sock *sk)
166 166
167 tcp_sw_conn->old_write_space(sk); 167 tcp_sw_conn->old_write_space(sk);
168 ISCSI_SW_TCP_DBG(conn, "iscsi_write_space\n"); 168 ISCSI_SW_TCP_DBG(conn, "iscsi_write_space\n");
169 scsi_queue_work(conn->session->host, &conn->xmitwork); 169 iscsi_conn_queue_work(conn);
170} 170}
171 171
172static void iscsi_sw_tcp_conn_set_callbacks(struct iscsi_conn *conn) 172static void iscsi_sw_tcp_conn_set_callbacks(struct iscsi_conn *conn)
@@ -777,7 +777,7 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
777 return NULL; 777 return NULL;
778 } 778 }
779 779
780 shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, qdepth); 780 shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, qdepth, 1);
781 if (!shost) 781 if (!shost)
782 return NULL; 782 return NULL;
783 shost->transportt = iscsi_sw_tcp_scsi_transport; 783 shost->transportt = iscsi_sw_tcp_scsi_transport;
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index a5168a673503..ff891543df22 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -76,6 +76,15 @@ static int iscsi_sna_lte(u32 n1, u32 n2)
76 (n1 > n2 && (n2 - n1 < SNA32_CHECK))); 76 (n1 > n2 && (n2 - n1 < SNA32_CHECK)));
77} 77}
78 78
79inline void iscsi_conn_queue_work(struct iscsi_conn *conn)
80{
81 struct Scsi_Host *shost = conn->session->host;
82 struct iscsi_host *ihost = shost_priv(shost);
83
84 queue_work(ihost->workq, &conn->xmitwork);
85}
86EXPORT_SYMBOL_GPL(iscsi_conn_queue_work);
87
79void 88void
80iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) 89iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
81{ 90{
@@ -103,8 +112,7 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
103 if (!list_empty(&session->leadconn->xmitqueue) || 112 if (!list_empty(&session->leadconn->xmitqueue) ||
104 !list_empty(&session->leadconn->mgmtqueue)) { 113 !list_empty(&session->leadconn->mgmtqueue)) {
105 if (!(session->tt->caps & CAP_DATA_PATH_OFFLOAD)) 114 if (!(session->tt->caps & CAP_DATA_PATH_OFFLOAD))
106 scsi_queue_work(session->host, 115 iscsi_conn_queue_work(session->leadconn);
107 &session->leadconn->xmitwork);
108 } 116 }
109 } 117 }
110} 118}
@@ -586,7 +594,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
586 goto free_task; 594 goto free_task;
587 595
588 } else 596 } else
589 scsi_queue_work(conn->session->host, &conn->xmitwork); 597 iscsi_conn_queue_work(conn);
590 598
591 return task; 599 return task;
592 600
@@ -1160,7 +1168,7 @@ void iscsi_requeue_task(struct iscsi_task *task)
1160 struct iscsi_conn *conn = task->conn; 1168 struct iscsi_conn *conn = task->conn;
1161 1169
1162 list_move_tail(&task->running, &conn->requeue); 1170 list_move_tail(&task->running, &conn->requeue);
1163 scsi_queue_work(conn->session->host, &conn->xmitwork); 1171 iscsi_conn_queue_work(conn);
1164} 1172}
1165EXPORT_SYMBOL_GPL(iscsi_requeue_task); 1173EXPORT_SYMBOL_GPL(iscsi_requeue_task);
1166 1174
@@ -1413,7 +1421,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
1413 goto prepd_reject; 1421 goto prepd_reject;
1414 } 1422 }
1415 } else 1423 } else
1416 scsi_queue_work(session->host, &conn->xmitwork); 1424 iscsi_conn_queue_work(conn);
1417 1425
1418 session->queued_cmdsn++; 1426 session->queued_cmdsn++;
1419 spin_unlock(&session->lock); 1427 spin_unlock(&session->lock);
@@ -1631,9 +1639,12 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun,
1631 1639
1632void iscsi_suspend_tx(struct iscsi_conn *conn) 1640void iscsi_suspend_tx(struct iscsi_conn *conn)
1633{ 1641{
1642 struct Scsi_Host *shost = conn->session->host;
1643 struct iscsi_host *ihost = shost_priv(shost);
1644
1634 set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); 1645 set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
1635 if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD)) 1646 if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD))
1636 scsi_flush_work(conn->session->host); 1647 flush_workqueue(ihost->workq);
1637} 1648}
1638EXPORT_SYMBOL_GPL(iscsi_suspend_tx); 1649EXPORT_SYMBOL_GPL(iscsi_suspend_tx);
1639 1650
@@ -1641,7 +1652,7 @@ static void iscsi_start_tx(struct iscsi_conn *conn)
1641{ 1652{
1642 clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); 1653 clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
1643 if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD)) 1654 if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD))
1644 scsi_queue_work(conn->session->host, &conn->xmitwork); 1655 iscsi_conn_queue_work(conn);
1645} 1656}
1646 1657
1647static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) 1658static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
@@ -2046,12 +2057,14 @@ EXPORT_SYMBOL_GPL(iscsi_host_add);
2046 * @sht: scsi host template 2057 * @sht: scsi host template
2047 * @dd_data_size: driver host data size 2058 * @dd_data_size: driver host data size
2048 * @qdepth: default device queue depth 2059 * @qdepth: default device queue depth
2060 * @xmit_can_sleep: bool indicating if LLD will queue IO from a work queue
2049 * 2061 *
2050 * This should be called by partial offload and software iscsi drivers. 2062 * This should be called by partial offload and software iscsi drivers.
2051 * To access the driver specific memory use the iscsi_host_priv() macro. 2063 * To access the driver specific memory use the iscsi_host_priv() macro.
2052 */ 2064 */
2053struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, 2065struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
2054 int dd_data_size, uint16_t qdepth) 2066 int dd_data_size, uint16_t qdepth,
2067 bool xmit_can_sleep)
2055{ 2068{
2056 struct Scsi_Host *shost; 2069 struct Scsi_Host *shost;
2057 struct iscsi_host *ihost; 2070 struct iscsi_host *ihost;
@@ -2063,13 +2076,25 @@ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
2063 if (qdepth == 0) 2076 if (qdepth == 0)
2064 qdepth = ISCSI_DEF_CMD_PER_LUN; 2077 qdepth = ISCSI_DEF_CMD_PER_LUN;
2065 shost->cmd_per_lun = qdepth; 2078 shost->cmd_per_lun = qdepth;
2066
2067 ihost = shost_priv(shost); 2079 ihost = shost_priv(shost);
2080
2081 if (xmit_can_sleep) {
2082 snprintf(ihost->workq_name, sizeof(ihost->workq_name),
2083 "iscsi_q_%d", shost->host_no);
2084 ihost->workq = create_singlethread_workqueue(ihost->workq_name);
2085 if (!ihost->workq)
2086 goto free_host;
2087 }
2088
2068 spin_lock_init(&ihost->lock); 2089 spin_lock_init(&ihost->lock);
2069 ihost->state = ISCSI_HOST_SETUP; 2090 ihost->state = ISCSI_HOST_SETUP;
2070 ihost->num_sessions = 0; 2091 ihost->num_sessions = 0;
2071 init_waitqueue_head(&ihost->session_removal_wq); 2092 init_waitqueue_head(&ihost->session_removal_wq);
2072 return shost; 2093 return shost;
2094
2095free_host:
2096 scsi_host_put(shost);
2097 return NULL;
2073} 2098}
2074EXPORT_SYMBOL_GPL(iscsi_host_alloc); 2099EXPORT_SYMBOL_GPL(iscsi_host_alloc);
2075 2100
@@ -2101,6 +2126,8 @@ void iscsi_host_remove(struct Scsi_Host *shost)
2101 flush_signals(current); 2126 flush_signals(current);
2102 2127
2103 scsi_remove_host(shost); 2128 scsi_remove_host(shost);
2129 if (ihost->workq)
2130 destroy_workqueue(ihost->workq);
2104} 2131}
2105EXPORT_SYMBOL_GPL(iscsi_host_remove); 2132EXPORT_SYMBOL_GPL(iscsi_host_remove);
2106 2133
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 898de4a73727..b0b8a6992497 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -318,6 +318,9 @@ struct iscsi_host {
318 spinlock_t lock; 318 spinlock_t lock;
319 int num_sessions; 319 int num_sessions;
320 int state; 320 int state;
321
322 struct workqueue_struct *workq;
323 char workq_name[20];
321}; 324};
322 325
323/* 326/*
@@ -343,7 +346,8 @@ extern int iscsi_host_get_param(struct Scsi_Host *shost,
343 enum iscsi_host_param param, char *buf); 346 enum iscsi_host_param param, char *buf);
344extern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev); 347extern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev);
345extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, 348extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
346 int dd_data_size, uint16_t qdepth); 349 int dd_data_size, uint16_t qdepth,
350 bool xmit_can_sleep);
347extern void iscsi_host_remove(struct Scsi_Host *shost); 351extern void iscsi_host_remove(struct Scsi_Host *shost);
348extern void iscsi_host_free(struct Scsi_Host *shost); 352extern void iscsi_host_free(struct Scsi_Host *shost);
349 353
@@ -379,6 +383,7 @@ extern void iscsi_session_failure(struct iscsi_cls_session *cls_session,
379extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, 383extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
380 enum iscsi_param param, char *buf); 384 enum iscsi_param param, char *buf);
381extern void iscsi_suspend_tx(struct iscsi_conn *conn); 385extern void iscsi_suspend_tx(struct iscsi_conn *conn);
386extern void iscsi_conn_queue_work(struct iscsi_conn *conn);
382 387
383#define iscsi_conn_printk(prefix, _c, fmt, a...) \ 388#define iscsi_conn_printk(prefix, _c, fmt, a...) \
384 iscsi_cls_conn_printk(prefix, ((struct iscsi_conn *)_c)->cls_conn, \ 389 iscsi_cls_conn_printk(prefix, ((struct iscsi_conn *)_c)->cls_conn, \