|
@@ -17,7 +17,7 @@
|
|
******************************************************************************/
|
|
******************************************************************************/
|
|
|
|
|
|
#include <linux/list.h>
|
|
#include <linux/list.h>
|
|
-#include <linux/percpu_ida.h>
|
|
|
|
|
|
+#include <linux/sched/signal.h>
|
|
#include <net/ipv6.h> /* ipv6_addr_equal() */
|
|
#include <net/ipv6.h> /* ipv6_addr_equal() */
|
|
#include <scsi/scsi_tcq.h>
|
|
#include <scsi/scsi_tcq.h>
|
|
#include <scsi/iscsi_proto.h>
|
|
#include <scsi/iscsi_proto.h>
|
|
@@ -147,6 +147,30 @@ void iscsit_free_r2ts_from_list(struct iscsi_cmd *cmd)
|
|
spin_unlock_bh(&cmd->r2t_lock);
|
|
spin_unlock_bh(&cmd->r2t_lock);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int iscsit_wait_for_tag(struct se_session *se_sess, int state, int *cpup)
|
|
|
|
+{
|
|
|
|
+ int tag = -1;
|
|
|
|
+ DEFINE_WAIT(wait);
|
|
|
|
+ struct sbq_wait_state *ws;
|
|
|
|
+
|
|
|
|
+ if (state == TASK_RUNNING)
|
|
|
|
+ return tag;
|
|
|
|
+
|
|
|
|
+ ws = &se_sess->sess_tag_pool.ws[0];
|
|
|
|
+ for (;;) {
|
|
|
|
+ prepare_to_wait_exclusive(&ws->wait, &wait, state);
|
|
|
|
+ if (signal_pending_state(state, current))
|
|
|
|
+ break;
|
|
|
|
+ tag = sbitmap_queue_get(&se_sess->sess_tag_pool, cpup);
|
|
|
|
+ if (tag >= 0)
|
|
|
|
+ break;
|
|
|
|
+ schedule();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ finish_wait(&ws->wait, &wait);
|
|
|
|
+ return tag;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* May be called from software interrupt (timer) context for allocating
|
|
* May be called from software interrupt (timer) context for allocating
|
|
* iSCSI NopINs.
|
|
* iSCSI NopINs.
|
|
@@ -155,9 +179,11 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, int state)
|
|
{
|
|
{
|
|
struct iscsi_cmd *cmd;
|
|
struct iscsi_cmd *cmd;
|
|
struct se_session *se_sess = conn->sess->se_sess;
|
|
struct se_session *se_sess = conn->sess->se_sess;
|
|
- int size, tag;
|
|
|
|
|
|
+ int size, tag, cpu;
|
|
|
|
|
|
- tag = percpu_ida_alloc(&se_sess->sess_tag_pool, state);
|
|
|
|
|
|
+ tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu);
|
|
|
|
+ if (tag < 0)
|
|
|
|
+ tag = iscsit_wait_for_tag(se_sess, state, &cpu);
|
|
if (tag < 0)
|
|
if (tag < 0)
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
@@ -166,6 +192,7 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, int state)
|
|
memset(cmd, 0, size);
|
|
memset(cmd, 0, size);
|
|
|
|
|
|
cmd->se_cmd.map_tag = tag;
|
|
cmd->se_cmd.map_tag = tag;
|
|
|
|
+ cmd->se_cmd.map_cpu = cpu;
|
|
cmd->conn = conn;
|
|
cmd->conn = conn;
|
|
cmd->data_direction = DMA_NONE;
|
|
cmd->data_direction = DMA_NONE;
|
|
INIT_LIST_HEAD(&cmd->i_conn_node);
|
|
INIT_LIST_HEAD(&cmd->i_conn_node);
|