Pull ticket4byte into release branch
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / scsi / cxgb3i / cxgb3i_iscsi.c
index 9212400..2631bdd 100644 (file)
@@ -13,6 +13,8 @@
 
 #include <linux/inet.h>
 #include <linux/crypto.h>
+#include <linux/if_vlan.h>
+#include <net/dst.h>
 #include <net/tcp.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
@@ -178,11 +180,14 @@ void cxgb3i_adapter_close(struct t3cdev *t3dev)
  * cxgb3i_hba_find_by_netdev - find the cxgb3i_hba structure via net_device
  * @t3dev: t3cdev adapter
  */
-struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev)
+static struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev)
 {
        struct cxgb3i_adapter *snic;
        int i;
 
+       if (ndev->priv_flags & IFF_802_1Q_VLAN)
+               ndev = vlan_dev_real_dev(ndev);
+
        read_lock(&cxgb3i_snic_rwlock);
        list_for_each_entry(snic, &cxgb3i_snic_list, list_head) {
                for (i = 0; i < snic->hba_cnt; i++) {
@@ -261,20 +266,27 @@ void cxgb3i_hba_host_remove(struct cxgb3i_hba *hba)
 
 /**
  * cxgb3i_ep_connect - establish TCP connection to target portal
+ * @shost:             scsi host to use
  * @dst_addr:          target IP address
  * @non_blocking:      blocking or non-blocking call
  *
  * Initiates a TCP/IP connection to the dst_addr
  */
-static struct iscsi_endpoint *cxgb3i_ep_connect(struct sockaddr *dst_addr,
+static struct iscsi_endpoint *cxgb3i_ep_connect(struct Scsi_Host *shost,
+                                               struct sockaddr *dst_addr,
                                                int non_blocking)
 {
        struct iscsi_endpoint *ep;
        struct cxgb3i_endpoint *cep;
-       struct cxgb3i_hba *hba;
+       struct cxgb3i_hba *hba = NULL;
        struct s3_conn *c3cn = NULL;
        int err = 0;
 
+       if (shost)
+               hba = iscsi_host_priv(shost);
+
+       cxgb3i_api_debug("shost 0x%p, hba 0x%p.\n", shost, hba);
+
        c3cn = cxgb3i_c3cn_create();
        if (!c3cn) {
                cxgb3i_log_info("ep connect OOM.\n");
@@ -282,17 +294,27 @@ static struct iscsi_endpoint *cxgb3i_ep_connect(struct sockaddr *dst_addr,
                goto release_conn;
        }
 
-       err = cxgb3i_c3cn_connect(c3cn, (struct sockaddr_in *)dst_addr);
+       err = cxgb3i_c3cn_connect(hba ? hba->ndev : NULL, c3cn,
+                                (struct sockaddr_in *)dst_addr);
        if (err < 0) {
                cxgb3i_log_info("ep connect failed.\n");
                goto release_conn;
        }
+
        hba = cxgb3i_hba_find_by_netdev(c3cn->dst_cache->dev);
        if (!hba) {
                err = -ENOSPC;
                cxgb3i_log_info("NOT going through cxgbi device.\n");
                goto release_conn;
        }
+
+       if (shost && hba != iscsi_host_priv(shost)) {
+               err = -ENOSPC;
+               cxgb3i_log_info("Could not connect through request host%u\n",
+                               shost->host_no);
+               goto release_conn;
+       }
+
        if (c3cn_is_closing(c3cn)) {
                err = -ENOSPC;
                cxgb3i_log_info("ep connect unable to connect.\n");
@@ -400,7 +422,7 @@ cxgb3i_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth,
        BUG_ON(hba != iscsi_host_priv(shost));
 
        cls_session = iscsi_session_setup(&cxgb3i_iscsi_transport, shost,
-                                         cmds_max,
+                                         cmds_max, 0,
                                          sizeof(struct iscsi_tcp_task) +
                                          sizeof(struct cxgb3i_task_data),
                                          initial_cmdsn, ISCSI_MAX_TARGET);