rk3368: add extra name for grf,sgrf,pmu-grf syscon node
[firefly-linux-kernel-4.4.55.git] / drivers / scsi / iscsi_tcp.c
index 3df985305f69eb3447827ff310063e4359009266..9e2588a6881cb72751ece0f0d2092f2e6e214353 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/delay.h>
 #include <linux/kfifo.h>
 #include <linux/scatterlist.h>
+#include <linux/module.h>
 #include <net/tcp.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
@@ -54,7 +55,7 @@ static struct scsi_transport_template *iscsi_sw_tcp_scsi_transport;
 static struct scsi_host_template iscsi_sw_tcp_sht;
 static struct iscsi_transport iscsi_sw_tcp_transport;
 
-static unsigned int iscsi_max_lun = 512;
+static unsigned int iscsi_max_lun = ~0;
 module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
 
 static int iscsi_sw_tcp_dbg;
@@ -107,10 +108,12 @@ static int iscsi_sw_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
  * If the socket is in CLOSE or CLOSE_WAIT we should
  * not close the connection if there is still some
  * data pending.
+ *
+ * Must be called with sk_callback_lock.
  */
 static inline int iscsi_sw_sk_state_check(struct sock *sk)
 {
-       struct iscsi_conn *conn = (struct iscsi_conn*)sk->sk_user_data;
+       struct iscsi_conn *conn = sk->sk_user_data;
 
        if ((sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) &&
            !atomic_read(&sk->sk_rmem_alloc)) {
@@ -123,11 +126,17 @@ static inline int iscsi_sw_sk_state_check(struct sock *sk)
 
 static void iscsi_sw_tcp_data_ready(struct sock *sk, int flag)
 {
-       struct iscsi_conn *conn = sk->sk_user_data;
-       struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+       struct iscsi_conn *conn;
+       struct iscsi_tcp_conn *tcp_conn;
        read_descriptor_t rd_desc;
 
        read_lock(&sk->sk_callback_lock);
+       conn = sk->sk_user_data;
+       if (!conn) {
+               read_unlock(&sk->sk_callback_lock);
+               return;
+       }
+       tcp_conn = conn->dd_data;
 
        /*
         * Use rd_desc to pass 'conn' to iscsi_tcp_recv.
@@ -141,11 +150,10 @@ static void iscsi_sw_tcp_data_ready(struct sock *sk, int flag)
 
        iscsi_sw_sk_state_check(sk);
 
-       read_unlock(&sk->sk_callback_lock);
-
        /* If we had to (atomically) map a highmem page,
         * unmap it now. */
        iscsi_tcp_segment_unmap(&tcp_conn->in.segment);
+       read_unlock(&sk->sk_callback_lock);
 }
 
 static void iscsi_sw_tcp_state_change(struct sock *sk)
@@ -157,8 +165,11 @@ static void iscsi_sw_tcp_state_change(struct sock *sk)
        void (*old_state_change)(struct sock *);
 
        read_lock(&sk->sk_callback_lock);
-
-       conn = (struct iscsi_conn*)sk->sk_user_data;
+       conn = sk->sk_user_data;
+       if (!conn) {
+               read_unlock(&sk->sk_callback_lock);
+               return;
+       }
        session = conn->session;
 
        iscsi_sw_sk_state_check(sk);
@@ -178,11 +189,25 @@ static void iscsi_sw_tcp_state_change(struct sock *sk)
  **/
 static void iscsi_sw_tcp_write_space(struct sock *sk)
 {
-       struct iscsi_conn *conn = (struct iscsi_conn*)sk->sk_user_data;
-       struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-       struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+       struct iscsi_conn *conn;
+       struct iscsi_tcp_conn *tcp_conn;
+       struct iscsi_sw_tcp_conn *tcp_sw_conn;
+       void (*old_write_space)(struct sock *);
+
+       read_lock_bh(&sk->sk_callback_lock);
+       conn = sk->sk_user_data;
+       if (!conn) {
+               read_unlock_bh(&sk->sk_callback_lock);
+               return;
+       }
+
+       tcp_conn = conn->dd_data;
+       tcp_sw_conn = tcp_conn->dd_data;
+       old_write_space = tcp_sw_conn->old_write_space;
+       read_unlock_bh(&sk->sk_callback_lock);
+
+       old_write_space(sk);
 
-       tcp_sw_conn->old_write_space(sk);
        ISCSI_SW_TCP_DBG(conn, "iscsi_write_space\n");
        iscsi_conn_queue_work(conn);
 }
@@ -345,17 +370,24 @@ static inline int iscsi_sw_tcp_xmit_qlen(struct iscsi_conn *conn)
 static int iscsi_sw_tcp_pdu_xmit(struct iscsi_task *task)
 {
        struct iscsi_conn *conn = task->conn;
-       int rc;
+       unsigned long pflags = current->flags;
+       int rc = 0;
+
+       current->flags |= PF_MEMALLOC;
 
        while (iscsi_sw_tcp_xmit_qlen(conn)) {
                rc = iscsi_sw_tcp_xmit(conn);
-               if (rc == 0)
-                       return -EAGAIN;
+               if (rc == 0) {
+                       rc = -EAGAIN;
+                       break;
+               }
                if (rc < 0)
-                       return rc;
+                       break;
+               rc = 0;
        }
 
-       return 0;
+       tsk_restore_flags(current, pflags, PF_MEMALLOC);
+       return rc;
 }
 
 /*
@@ -592,20 +624,17 @@ static void iscsi_sw_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
        /* userspace may have goofed up and not bound us */
        if (!sock)
                return;
-       /*
-        * Make sure our recv side is stopped.
-        * Older tools called conn stop before ep_disconnect
-        * so IO could still be coming in.
-        */
-       write_lock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock);
-       set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
-       write_unlock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock);
 
        sock->sk->sk_err = EIO;
        wake_up_interruptible(sk_sleep(sock->sk));
 
-       iscsi_conn_stop(cls_conn, flag);
+       /* stop xmit side */
+       iscsi_suspend_tx(conn);
+
+       /* stop recv side and release socket */
        iscsi_sw_tcp_release_conn(conn);
+
+       iscsi_conn_stop(cls_conn, flag);
 }
 
 static int
@@ -640,9 +669,10 @@ iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session,
 
        /* setup Socket parameters */
        sk = sock->sk;
-       sk->sk_reuse = 1;
+       sk->sk_reuse = SK_CAN_REUSE;
        sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */
        sk->sk_allocation = GFP_ATOMIC;
+       sk_set_memalloc(sk);
 
        iscsi_sw_tcp_conn_set_callbacks(conn);
        tcp_sw_conn->sendpage = tcp_sw_conn->sock->ops->sendpage;
@@ -662,10 +692,8 @@ static int iscsi_sw_tcp_conn_set_param(struct iscsi_cls_conn *cls_conn,
                                       int buflen)
 {
        struct iscsi_conn *conn = cls_conn->dd_data;
-       struct iscsi_session *session = conn->session;
        struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
        struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
-       int value;
 
        switch(param) {
        case ISCSI_PARAM_HDRDGST_EN:
@@ -677,16 +705,7 @@ static int iscsi_sw_tcp_conn_set_param(struct iscsi_cls_conn *cls_conn,
                        sock_no_sendpage : tcp_sw_conn->sock->ops->sendpage;
                break;
        case ISCSI_PARAM_MAX_R2T:
-               sscanf(buf, "%d", &value);
-               if (value <= 0 || !is_power_of_2(value))
-                       return -EINVAL;
-               if (session->max_r2t == value)
-                       break;
-               iscsi_tcp_r2tpool_free(session);
-               iscsi_set_param(cls_conn, param, buf, buflen);
-               if (iscsi_tcp_r2tpool_alloc(session))
-                       return -ENOMEM;
-               break;
+               return iscsi_tcp_set_max_r2t(conn, buf);
        default:
                return iscsi_set_param(cls_conn, param, buf, buflen);
        }
@@ -851,6 +870,61 @@ static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session)
        iscsi_host_free(shost);
 }
 
+static umode_t iscsi_sw_tcp_attr_is_visible(int param_type, int param)
+{
+       switch (param_type) {
+       case ISCSI_HOST_PARAM:
+               switch (param) {
+               case ISCSI_HOST_PARAM_NETDEV_NAME:
+               case ISCSI_HOST_PARAM_HWADDRESS:
+               case ISCSI_HOST_PARAM_IPADDRESS:
+               case ISCSI_HOST_PARAM_INITIATOR_NAME:
+                       return S_IRUGO;
+               default:
+                       return 0;
+               }
+       case ISCSI_PARAM:
+               switch (param) {
+               case ISCSI_PARAM_MAX_RECV_DLENGTH:
+               case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+               case ISCSI_PARAM_HDRDGST_EN:
+               case ISCSI_PARAM_DATADGST_EN:
+               case ISCSI_PARAM_CONN_ADDRESS:
+               case ISCSI_PARAM_CONN_PORT:
+               case ISCSI_PARAM_EXP_STATSN:
+               case ISCSI_PARAM_PERSISTENT_ADDRESS:
+               case ISCSI_PARAM_PERSISTENT_PORT:
+               case ISCSI_PARAM_PING_TMO:
+               case ISCSI_PARAM_RECV_TMO:
+               case ISCSI_PARAM_INITIAL_R2T_EN:
+               case ISCSI_PARAM_MAX_R2T:
+               case ISCSI_PARAM_IMM_DATA_EN:
+               case ISCSI_PARAM_FIRST_BURST:
+               case ISCSI_PARAM_MAX_BURST:
+               case ISCSI_PARAM_PDU_INORDER_EN:
+               case ISCSI_PARAM_DATASEQ_INORDER_EN:
+               case ISCSI_PARAM_ERL:
+               case ISCSI_PARAM_TARGET_NAME:
+               case ISCSI_PARAM_TPGT:
+               case ISCSI_PARAM_USERNAME:
+               case ISCSI_PARAM_PASSWORD:
+               case ISCSI_PARAM_USERNAME_IN:
+               case ISCSI_PARAM_PASSWORD_IN:
+               case ISCSI_PARAM_FAST_ABORT:
+               case ISCSI_PARAM_ABORT_TMO:
+               case ISCSI_PARAM_LU_RESET_TMO:
+               case ISCSI_PARAM_TGT_RESET_TMO:
+               case ISCSI_PARAM_IFACE_NAME:
+               case ISCSI_PARAM_INITIATOR_NAME:
+                       return S_IRUGO;
+               default:
+                       return 0;
+               }
+       }
+
+       return 0;
+}
+
 static int iscsi_sw_tcp_slave_alloc(struct scsi_device *sdev)
 {
        set_bit(QUEUE_FLAG_BIDI, &sdev->request_queue->queue_flags);
@@ -889,33 +963,6 @@ static struct iscsi_transport iscsi_sw_tcp_transport = {
        .name                   = "tcp",
        .caps                   = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
                                  | CAP_DATADGST,
-       .param_mask             = ISCSI_MAX_RECV_DLENGTH |
-                                 ISCSI_MAX_XMIT_DLENGTH |
-                                 ISCSI_HDRDGST_EN |
-                                 ISCSI_DATADGST_EN |
-                                 ISCSI_INITIAL_R2T_EN |
-                                 ISCSI_MAX_R2T |
-                                 ISCSI_IMM_DATA_EN |
-                                 ISCSI_FIRST_BURST |
-                                 ISCSI_MAX_BURST |
-                                 ISCSI_PDU_INORDER_EN |
-                                 ISCSI_DATASEQ_INORDER_EN |
-                                 ISCSI_ERL |
-                                 ISCSI_CONN_PORT |
-                                 ISCSI_CONN_ADDRESS |
-                                 ISCSI_EXP_STATSN |
-                                 ISCSI_PERSISTENT_PORT |
-                                 ISCSI_PERSISTENT_ADDRESS |
-                                 ISCSI_TARGET_NAME | ISCSI_TPGT |
-                                 ISCSI_USERNAME | ISCSI_PASSWORD |
-                                 ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
-                                 ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
-                                 ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
-                                 ISCSI_PING_TMO | ISCSI_RECV_TMO |
-                                 ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
-       .host_param_mask        = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
-                                 ISCSI_HOST_INITIATOR_NAME |
-                                 ISCSI_HOST_NETDEV_NAME,
        /* session management */
        .create_session         = iscsi_sw_tcp_session_create,
        .destroy_session        = iscsi_sw_tcp_session_destroy,
@@ -923,6 +970,7 @@ static struct iscsi_transport iscsi_sw_tcp_transport = {
        .create_conn            = iscsi_sw_tcp_conn_create,
        .bind_conn              = iscsi_sw_tcp_conn_bind,
        .destroy_conn           = iscsi_sw_tcp_conn_destroy,
+       .attr_is_visible        = iscsi_sw_tcp_attr_is_visible,
        .set_param              = iscsi_sw_tcp_conn_set_param,
        .get_conn_param         = iscsi_sw_tcp_conn_get_param,
        .get_session_param      = iscsi_session_get_param,