All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next v2 0/4] cxgb4i: Add ipv6 support
@ 2014-07-17  7:18 Anish Bhatt
  2014-07-17  7:18 ` [PATCH net-next v2 2/4] cxgb4: Export symbols required by cxgb4i for ipv6 support and required defines Anish Bhatt
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Anish Bhatt @ 2014-07-17  7:18 UTC (permalink / raw)
  To: netdev
  Cc: linux-rdma, linux-scsi, davem, roland, hch, michaelc, jbottomley,
	kxie, leedom, hariprasad, swise, Anish Bhatt

Hi,
   The following patchset add ipv6 support for the cxgb4i(iscsi) driver.

Patch 1 moves a define from the iw_cxgb4 to cxgb4 to prevent code duplication,
 as it is used by cxgb4i and iw_cxgb4 both.
Patch 2 exports symbols needed by cxgb4i for ipv6 support from cxgb4.
Patch 3 & 4 deal with actual ipv6 code in libcxgbi/cxgb4i.

Submitting to net-next as changes were needed in cxgb4/iw_cxgb4, and submitting
to scsi separately would break compilation, cc-ing scsi & rdma.

-Anish

v2 : Cleanup macro that prints ip addresses by using %pIS in patch 3

Anish Bhatt (4):
  cxgb4/iw_cxgb4: Move common defines to cxgb4
  cxgb4: Export symbols required by cxgb4i for ipv6 support and required
    defines
  libcxgbi: Add ipv6 api to driver
  cxgb4i: Add ipv6 code to driver, call into libcxgbi ipv6 api

 drivers/infiniband/hw/cxgb4/t4fw_ri_api.h       |   1 -
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c |  10 +-
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h  |   4 +
 drivers/net/ethernet/chelsio/cxgb4/t4_msg.h     |   3 +
 drivers/scsi/cxgbi/cxgb4i/cxgb4i.c              | 353 +++++++++++++++++++++---
 drivers/scsi/cxgbi/libcxgbi.c                   | 237 ++++++++++++++--
 drivers/scsi/cxgbi/libcxgbi.h                   |  21 +-
 7 files changed, 564 insertions(+), 65 deletions(-)

-- 
2.0.1

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH net-next v2 1/4] cxgb4/iw_cxgb4: Move common defines to cxgb4
       [not found] ` <1405581498-28092-1-git-send-email-anish-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
@ 2014-07-17  7:18   ` Anish Bhatt
  2014-07-17  7:18   ` [PATCH net-next v2 4/4] cxgb4i: Add ipv6 code to driver, call into libcxgbi ipv6 api Anish Bhatt
  2014-07-17 23:06   ` [PATCH net-next v2 0/4] cxgb4i: Add ipv6 support David Miller
  2 siblings, 0 replies; 6+ messages in thread
From: Anish Bhatt @ 2014-07-17  7:18 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	linux-scsi-u79uwXL29TY76Z2rM5mHXA, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	roland-BHEL68pLQRGGvPXPguhicg, hch-wEGCiKHe2LqWVfeAwA7xHQ,
	michaelc-hcNo3dDEHLuVc3sceRu5cw,
	jbottomley-bzQdu9zFT3WakBO8gow8eQ, kxie-ut6Up61K2wZBDgjK7y7TUQ,
	leedom-ut6Up61K2wZBDgjK7y7TUQ, hariprasad-ut6Up61K2wZBDgjK7y7TUQ,
	swise-7bPotxP6k4+P2YhJcF5u+vpXobYPEAuW, Anish Bhatt

This define is used by cxgb4i and iw_cxgb4, moving to avoid code duplication

Signed-off-by: Anish Bhatt <anish-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
Acked-by: Steve Wise <swise-7bPotxP6k4+P2YhJcF5u+vpXobYPEAuW@public.gmane.org>
---
 drivers/infiniband/hw/cxgb4/t4fw_ri_api.h   | 1 -
 drivers/net/ethernet/chelsio/cxgb4/t4_msg.h | 1 +
 2 files changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h b/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h
index 91289a051af9..5709e77faf7c 100644
--- a/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h
+++ b/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h
@@ -849,6 +849,5 @@ enum {                     /* TCP congestion control algorithms */
 #define G_CONG_CNTRL(x) (((x) >> S_CONG_CNTRL) & M_CONG_CNTRL)
 
 #define CONG_CNTRL_VALID   (1 << 18)
-#define T5_OPT_2_VALID       (1 << 31)
 
 #endif /* _T4FW_RI_API_H_ */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
index abb45809c0c8..64006327df83 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
@@ -276,6 +276,7 @@ struct cpl_pass_accept_rpl {
 #define WND_SCALE_EN(x)      ((x) << 28)
 #define TSTAMPS_EN(x)        ((x) << 29)
 #define SACK_EN(x)           ((x) << 30)
+#define T5_OPT_2_VALID	     ((1U) << 31)
 	__be64 opt0;
 };
 
-- 
2.0.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH net-next v2 2/4] cxgb4: Export symbols required by cxgb4i for ipv6 support and required defines
  2014-07-17  7:18 [PATCH net-next v2 0/4] cxgb4i: Add ipv6 support Anish Bhatt
@ 2014-07-17  7:18 ` Anish Bhatt
  2014-07-17  7:18 ` [PATCH net-next v2 3/4] libcxgbi: Add ipv6 api to driver Anish Bhatt
       [not found] ` <1405581498-28092-1-git-send-email-anish-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
  2 siblings, 0 replies; 6+ messages in thread
From: Anish Bhatt @ 2014-07-17  7:18 UTC (permalink / raw)
  To: netdev
  Cc: linux-rdma, linux-scsi, davem, roland, hch, michaelc, jbottomley,
	kxie, leedom, hariprasad, swise, Anish Bhatt

Signed-off-by: Anish Bhatt <anish@chelsio.com>
---
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 10 ++++++----
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h  |  4 ++++
 drivers/net/ethernet/chelsio/cxgb4/t4_msg.h     |  2 ++
 3 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 9c7e4f0a7683..8b46534b06c1 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3445,8 +3445,8 @@ static int tid_init(struct tid_info *t)
 	return 0;
 }
 
-static int cxgb4_clip_get(const struct net_device *dev,
-			  const struct in6_addr *lip)
+int cxgb4_clip_get(const struct net_device *dev,
+		   const struct in6_addr *lip)
 {
 	struct adapter *adap;
 	struct fw_clip_cmd c;
@@ -3460,9 +3460,10 @@ static int cxgb4_clip_get(const struct net_device *dev,
 	c.ip_lo = *(__be64 *)(lip->s6_addr + 8);
 	return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, false);
 }
+EXPORT_SYMBOL(cxgb4_clip_get);
 
-static int cxgb4_clip_release(const struct net_device *dev,
-			      const struct in6_addr *lip)
+int cxgb4_clip_release(const struct net_device *dev,
+		       const struct in6_addr *lip)
 {
 	struct adapter *adap;
 	struct fw_clip_cmd c;
@@ -3476,6 +3477,7 @@ static int cxgb4_clip_release(const struct net_device *dev,
 	c.ip_lo = *(__be64 *)(lip->s6_addr + 8);
 	return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, false);
 }
+EXPORT_SYMBOL(cxgb4_clip_release);
 
 /**
  *	cxgb4_create_server - create an IP server
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index 79a84de1d204..1366ba620c87 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -172,6 +172,10 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
 			       unsigned char port, unsigned char mask);
 int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid,
 			       unsigned int queue, bool ipv6);
+int cxgb4_clip_get(const struct net_device *dev, const struct in6_addr *lip);
+int cxgb4_clip_release(const struct net_device *dev,
+		       const struct in6_addr *lip);
+
 static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue)
 {
 	skb_set_queue_mapping(skb, (queue << 1) | prio);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
index 64006327df83..0259feeab1b3 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
@@ -270,6 +270,8 @@ struct cpl_pass_accept_rpl {
 #define RX_COALESCE_VALID(x) ((x) << 11)
 #define RX_COALESCE(x)       ((x) << 12)
 #define PACE(x)	      ((x) << 16)
+#define RX_FC_VALID	     ((1U) << 19)
+#define RX_FC_DISABLE	     ((1U) << 20)
 #define TX_QUEUE(x)          ((x) << 23)
 #define RX_CHANNEL(x)        ((x) << 26)
 #define CCTRL_ECN(x)         ((x) << 27)
-- 
2.0.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH net-next v2 3/4] libcxgbi: Add ipv6 api to driver
  2014-07-17  7:18 [PATCH net-next v2 0/4] cxgb4i: Add ipv6 support Anish Bhatt
  2014-07-17  7:18 ` [PATCH net-next v2 2/4] cxgb4: Export symbols required by cxgb4i for ipv6 support and required defines Anish Bhatt
@ 2014-07-17  7:18 ` Anish Bhatt
       [not found] ` <1405581498-28092-1-git-send-email-anish-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
  2 siblings, 0 replies; 6+ messages in thread
From: Anish Bhatt @ 2014-07-17  7:18 UTC (permalink / raw)
  To: netdev
  Cc: linux-rdma, linux-scsi, davem, roland, hch, michaelc, jbottomley,
	kxie, leedom, hariprasad, swise, Anish Bhatt, Manoj Malviya

Signed-off-by: Anish Bhatt <anish@chelsio.com>
Signed-off-by: Karen Xie <kxie@chelsio.com>
Signed-off-by: Manoj Malviya <manojmalviya@chelsio.com>
---
 drivers/scsi/cxgbi/libcxgbi.c | 237 ++++++++++++++++++++++++++++++++++++++----
 drivers/scsi/cxgbi/libcxgbi.h |  21 +++-
 2 files changed, 237 insertions(+), 21 deletions(-)

diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
index b44c1cff3114..d2fe507fc695 100644
--- a/drivers/scsi/cxgbi/libcxgbi.c
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -24,6 +24,10 @@
 #include <linux/inet.h>
 #include <net/dst.h>
 #include <net/route.h>
+#include <net/ipv6.h>
+#include <net/ip6_route.h>
+#include <net/addrconf.h>
+
 #include <linux/inetdevice.h>	/* ip_dev_find */
 #include <linux/module.h>
 #include <net/tcp.h>
@@ -193,8 +197,8 @@ struct cxgbi_device *cxgbi_device_find_by_lldev(void *lldev)
 }
 EXPORT_SYMBOL_GPL(cxgbi_device_find_by_lldev);
 
-static struct cxgbi_device *cxgbi_device_find_by_netdev(struct net_device *ndev,
-							int *port)
+struct cxgbi_device *cxgbi_device_find_by_netdev(struct net_device *ndev,
+						 int *port)
 {
 	struct net_device *vdev = NULL;
 	struct cxgbi_device *cdev, *tmp;
@@ -224,6 +228,40 @@ static struct cxgbi_device *cxgbi_device_find_by_netdev(struct net_device *ndev,
 		"ndev 0x%p, %s, NO match found.\n", ndev, ndev->name);
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(cxgbi_device_find_by_netdev);
+
+static struct cxgbi_device *cxgbi_device_find_by_mac(struct net_device *ndev,
+						     int *port)
+{
+	struct net_device *vdev = NULL;
+	struct cxgbi_device *cdev, *tmp;
+	int i;
+
+	if (ndev->priv_flags & IFF_802_1Q_VLAN) {
+		vdev = ndev;
+		ndev = vlan_dev_real_dev(ndev);
+		pr_info("vlan dev %s -> %s.\n", vdev->name, ndev->name);
+	}
+
+	mutex_lock(&cdev_mutex);
+	list_for_each_entry_safe(cdev, tmp, &cdev_list, list_head) {
+		for (i = 0; i < cdev->nports; i++) {
+			if (!memcmp(ndev->dev_addr, cdev->ports[i]->dev_addr,
+				    MAX_ADDR_LEN)) {
+				cdev->hbas[i]->vdev = vdev;
+				mutex_unlock(&cdev_mutex);
+				if (port)
+					*port = i;
+				return cdev;
+			}
+		}
+	}
+	mutex_unlock(&cdev_mutex);
+	log_debug(1 << CXGBI_DBG_DEV,
+		  "ndev 0x%p, %s, NO match mac found.\n",
+		  ndev, ndev->name);
+	return NULL;
+}
 
 void cxgbi_hbas_remove(struct cxgbi_device *cdev)
 {
@@ -320,6 +358,7 @@ static int sock_get_port(struct cxgbi_sock *csk)
 	struct cxgbi_ports_map *pmap = &cdev->pmap;
 	unsigned int start;
 	int idx;
+	__be16 *port;
 
 	if (!pmap->max_connect) {
 		pr_err("cdev 0x%p, p#%u %s, NO port map.\n",
@@ -327,9 +366,14 @@ static int sock_get_port(struct cxgbi_sock *csk)
 		return -EADDRNOTAVAIL;
 	}
 
-	if (csk->saddr.sin_port) {
+	if (csk->csk_family == AF_INET)
+		port = &csk->saddr.sin_port;
+	else /* ipv6 */
+		port = &csk->saddr6.sin6_port;
+
+	if (*port) {
 		pr_err("source port NON-ZERO %u.\n",
-			ntohs(csk->saddr.sin_port));
+			ntohs(*port));
 		return -EADDRINUSE;
 	}
 
@@ -347,8 +391,7 @@ static int sock_get_port(struct cxgbi_sock *csk)
 			idx = 0;
 		if (!pmap->port_csk[idx]) {
 			pmap->used++;
-			csk->saddr.sin_port =
-				htons(pmap->sport_base + idx);
+			*port = htons(pmap->sport_base + idx);
 			pmap->next = idx;
 			pmap->port_csk[idx] = csk;
 			spin_unlock_bh(&pmap->lock);
@@ -374,16 +417,22 @@ static void sock_put_port(struct cxgbi_sock *csk)
 {
 	struct cxgbi_device *cdev = csk->cdev;
 	struct cxgbi_ports_map *pmap = &cdev->pmap;
+	__be16 *port;
 
-	if (csk->saddr.sin_port) {
-		int idx = ntohs(csk->saddr.sin_port) - pmap->sport_base;
+	if (csk->csk_family == AF_INET)
+		port = &csk->saddr.sin_port;
+	else /* ipv6 */
+		port = &csk->saddr6.sin6_port;
 
-		csk->saddr.sin_port = 0;
+	if (*port) {
+		int idx = ntohs(*port) - pmap->sport_base;
+
+		*port = 0;
 		if (idx < 0 || idx >= pmap->max_connect) {
 			pr_err("cdev 0x%p, p#%u %s, port %u OOR.\n",
 				cdev, csk->port_id,
 				cdev->ports[csk->port_id]->name,
-				ntohs(csk->saddr.sin_port));
+				ntohs(*port));
 			return;
 		}
 
@@ -479,17 +528,11 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr)
 	int port = 0xFFFF;
 	int err = 0;
 
-	if (daddr->sin_family != AF_INET) {
-		pr_info("address family 0x%x NOT supported.\n",
-			daddr->sin_family);
-		err = -EAFNOSUPPORT;
-		goto err_out;
-	}
-
 	rt = find_route_ipv4(&fl4, 0, daddr->sin_addr.s_addr, 0, daddr->sin_port, 0);
 	if (!rt) {
 		pr_info("no route to ipv4 0x%x, port %u.\n",
-			daddr->sin_addr.s_addr, daddr->sin_port);
+			be32_to_cpu(daddr->sin_addr.s_addr),
+			be16_to_cpu(daddr->sin_port));
 		err = -ENETUNREACH;
 		goto err_out;
 	}
@@ -537,9 +580,12 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr)
 	csk->port_id = port;
 	csk->mtu = mtu;
 	csk->dst = dst;
+
+	csk->csk_family = AF_INET;
 	csk->daddr.sin_addr.s_addr = daddr->sin_addr.s_addr;
 	csk->daddr.sin_port = daddr->sin_port;
 	csk->daddr.sin_family = daddr->sin_family;
+	csk->saddr.sin_family = daddr->sin_family;
 	csk->saddr.sin_addr.s_addr = fl4.saddr;
 	neigh_release(n);
 
@@ -556,6 +602,121 @@ err_out:
 	return ERR_PTR(err);
 }
 
+static struct rt6_info *find_route_ipv6(const struct in6_addr *saddr,
+					const struct in6_addr *daddr)
+{
+	struct flowi6 fl;
+
+	if (saddr)
+		memcpy(&fl.saddr, saddr, sizeof(struct in6_addr));
+	if (daddr)
+		memcpy(&fl.daddr, daddr, sizeof(struct in6_addr));
+	return (struct rt6_info *)ip6_route_output(&init_net, NULL, &fl);
+}
+
+static struct cxgbi_sock *cxgbi_check_route6(struct sockaddr *dst_addr)
+{
+	struct sockaddr_in6 *daddr6 = (struct sockaddr_in6 *)dst_addr;
+	struct dst_entry *dst;
+	struct net_device *ndev;
+	struct cxgbi_device *cdev;
+	struct rt6_info *rt = NULL;
+	struct neighbour *n;
+	struct in6_addr pref_saddr;
+	struct cxgbi_sock *csk = NULL;
+	unsigned int mtu = 0;
+	int port = 0xFFFF;
+	int err = 0;
+
+	rt = find_route_ipv6(NULL, &daddr6->sin6_addr);
+
+	if (!rt) {
+		pr_info("no route to ipv6 %pI6 port %u\n",
+			daddr6->sin6_addr.s6_addr,
+			be16_to_cpu(daddr6->sin6_port));
+		err = -ENETUNREACH;
+		goto err_out;
+	}
+
+	dst = &rt->dst;
+
+	n = dst_neigh_lookup(dst, &daddr6->sin6_addr);
+
+	if (!n) {
+		pr_info("%pI6, port %u, dst no neighbour.\n",
+			daddr6->sin6_addr.s6_addr,
+			be16_to_cpu(daddr6->sin6_port));
+		err = -ENETUNREACH;
+		goto rel_rt;
+	}
+	ndev = n->dev;
+
+	if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) {
+		pr_info("multi-cast route %pI6 port %u, dev %s.\n",
+			daddr6->sin6_addr.s6_addr,
+			ntohs(daddr6->sin6_port), ndev->name);
+		err = -ENETUNREACH;
+		goto rel_rt;
+	}
+
+	cdev = cxgbi_device_find_by_netdev(ndev, &port);
+	if (!cdev)
+		cdev = cxgbi_device_find_by_mac(ndev, &port);
+	if (!cdev) {
+		pr_info("dst %pI6 %s, NOT cxgbi device.\n",
+			daddr6->sin6_addr.s6_addr, ndev->name);
+		err = -ENETUNREACH;
+		goto rel_rt;
+	}
+	log_debug(1 << CXGBI_DBG_SOCK,
+		  "route to %pI6 :%u, ndev p#%d,%s, cdev 0x%p.\n",
+		  daddr6->sin6_addr.s6_addr, ntohs(daddr6->sin6_port), port,
+		  ndev->name, cdev);
+
+	csk = cxgbi_sock_create(cdev);
+	if (!csk) {
+		err = -ENOMEM;
+		goto rel_rt;
+	}
+	csk->cdev = cdev;
+	csk->port_id = port;
+	csk->mtu = mtu;
+	csk->dst = dst;
+
+	if (ipv6_addr_any(&rt->rt6i_prefsrc.addr)) {
+		struct inet6_dev *idev = ip6_dst_idev((struct dst_entry *)rt);
+
+		err = ipv6_dev_get_saddr(&init_net, idev ? idev->dev : NULL,
+					 &daddr6->sin6_addr, 0, &pref_saddr);
+		if (err) {
+			pr_info("failed to get source address to reach %pI6\n",
+				&daddr6->sin6_addr);
+			goto rel_rt;
+		}
+	} else {
+		pref_saddr = rt->rt6i_prefsrc.addr;
+	}
+
+	csk->csk_family = AF_INET6;
+	csk->daddr6.sin6_addr = daddr6->sin6_addr;
+	csk->daddr6.sin6_port = daddr6->sin6_port;
+	csk->daddr6.sin6_family = daddr6->sin6_family;
+	csk->saddr6.sin6_addr = pref_saddr;
+
+	neigh_release(n);
+	return csk;
+
+rel_rt:
+	if (n)
+		neigh_release(n);
+
+	ip6_rt_put(rt);
+	if (csk)
+		cxgbi_sock_closed(csk);
+err_out:
+	return ERR_PTR(err);
+}
+
 void cxgbi_sock_established(struct cxgbi_sock *csk, unsigned int snd_isn,
 			unsigned int opt)
 {
@@ -2194,6 +2355,34 @@ int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn,
 }
 EXPORT_SYMBOL_GPL(cxgbi_set_conn_param);
 
+static inline int csk_print_port(struct cxgbi_sock *csk, char *buf)
+{
+	int len;
+
+	cxgbi_sock_get(csk);
+	len = sprintf(buf, "%hu\n", ntohs(csk->daddr.sin_port));
+	cxgbi_sock_put(csk);
+
+	return len;
+}
+
+static inline int csk_print_ip(struct cxgbi_sock *csk, char *buf)
+{
+	int len;
+
+	cxgbi_sock_get(csk);
+	if (csk->csk_family == AF_INET)
+		len = sprintf(buf, "%pI4",
+			      &csk->daddr.sin_addr.s_addr);
+	else
+		len = sprintf(buf, "%pI6",
+			      &csk->daddr6.sin6_addr);
+
+	cxgbi_sock_put(csk);
+
+	return len;
+}
+
 int cxgbi_get_ep_param(struct iscsi_endpoint *ep, enum iscsi_param param,
 		       char *buf)
 {
@@ -2447,7 +2636,17 @@ struct iscsi_endpoint *cxgbi_ep_connect(struct Scsi_Host *shost,
 		}
 	}
 
-	csk = cxgbi_check_route(dst_addr);
+	if (dst_addr->sa_family == AF_INET) {
+		csk = cxgbi_check_route(dst_addr);
+	} else if (dst_addr->sa_family == AF_INET6) {
+		csk = cxgbi_check_route6(dst_addr);
+	} else {
+		pr_info("address family 0x%x NOT supported.\n",
+			dst_addr->sa_family);
+		err = -EAFNOSUPPORT;
+		return (struct iscsi_endpoint *)ERR_PTR(err);
+	}
+
 	if (IS_ERR(csk))
 		return (struct iscsi_endpoint *)csk;
 	cxgbi_sock_get(csk);
diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h
index 8135f04671af..8ad73d913f02 100644
--- a/drivers/scsi/cxgbi/libcxgbi.h
+++ b/drivers/scsi/cxgbi/libcxgbi.h
@@ -44,6 +44,15 @@ enum cxgbi_dbg_flag {
 			pr_info(fmt, ##__VA_ARGS__); \
 	} while (0)
 
+#define pr_info_ipaddr(fmt_trail,					\
+			addr1, addr2, args_trail...)			\
+do {									\
+	if (!((1 << CXGBI_DBG_SOCK) & dbg_level))			\
+		break;							\
+	pr_info("%pISpc - %pISpc, " fmt_trail,				\
+		addr1, addr2, args_trail);				\
+} while (0)
+
 /* max. connections per adapter */
 #define CXGBI_MAX_CONN		16384
 
@@ -202,8 +211,15 @@ struct cxgbi_sock {
 	spinlock_t lock;
 	struct kref refcnt;
 	unsigned int state;
-	struct sockaddr_in saddr;
-	struct sockaddr_in daddr;
+	unsigned int csk_family;
+	union {
+		struct sockaddr_in saddr;
+		struct sockaddr_in6 saddr6;
+	};
+	union {
+		struct sockaddr_in daddr;
+		struct sockaddr_in6 daddr6;
+	};
 	struct dst_entry *dst;
 	struct sk_buff_head receive_queue;
 	struct sk_buff_head write_queue;
@@ -692,6 +708,7 @@ struct cxgbi_device *cxgbi_device_register(unsigned int, unsigned int);
 void cxgbi_device_unregister(struct cxgbi_device *);
 void cxgbi_device_unregister_all(unsigned int flag);
 struct cxgbi_device *cxgbi_device_find_by_lldev(void *);
+struct cxgbi_device *cxgbi_device_find_by_netdev(struct net_device *, int *);
 int cxgbi_hbas_add(struct cxgbi_device *, unsigned int, unsigned int,
 			struct scsi_host_template *,
 			struct scsi_transport_template *);
-- 
2.0.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH net-next v2 4/4] cxgb4i: Add ipv6 code to driver, call into libcxgbi ipv6 api
       [not found] ` <1405581498-28092-1-git-send-email-anish-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
  2014-07-17  7:18   ` [PATCH net-next v2 1/4] cxgb4/iw_cxgb4: Move common defines to cxgb4 Anish Bhatt
@ 2014-07-17  7:18   ` Anish Bhatt
  2014-07-17 23:06   ` [PATCH net-next v2 0/4] cxgb4i: Add ipv6 support David Miller
  2 siblings, 0 replies; 6+ messages in thread
From: Anish Bhatt @ 2014-07-17  7:18 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	linux-scsi-u79uwXL29TY76Z2rM5mHXA, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	roland-BHEL68pLQRGGvPXPguhicg, hch-wEGCiKHe2LqWVfeAwA7xHQ,
	michaelc-hcNo3dDEHLuVc3sceRu5cw,
	jbottomley-bzQdu9zFT3WakBO8gow8eQ, kxie-ut6Up61K2wZBDgjK7y7TUQ,
	leedom-ut6Up61K2wZBDgjK7y7TUQ, hariprasad-ut6Up61K2wZBDgjK7y7TUQ,
	swise-7bPotxP6k4+P2YhJcF5u+vpXobYPEAuW, Anish Bhatt,
	Manoj Malviya

Signed-off-by: Anish Bhatt <anish-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
Signed-off-by: Karen Xie <kxie-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
Signed-off-by: Manoj Malviya <manojmalviya-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
---
 drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 353 +++++++++++++++++++++++++++++++++----
 1 file changed, 314 insertions(+), 39 deletions(-)

diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
index e8ee5e5fe0ef..1041574edcfc 100644
--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -19,6 +19,7 @@
 #include <net/tcp.h>
 #include <net/dst.h>
 #include <linux/netdevice.h>
+#include <net/addrconf.h>
 
 #include "t4_regs.h"
 #include "t4_msg.h"
@@ -150,6 +151,7 @@ static struct scsi_transport_template *cxgb4i_stt;
  * The section below implments CPLs that related to iscsi tcp connection
  * open/close/abort and data send/receive.
  */
+
 #define DIV_ROUND_UP(n, d)	(((n) + (d) - 1) / (d))
 #define RCV_BUFSIZ_MASK		0x3FFU
 #define MAX_IMM_TX_PKT_LEN	128
@@ -179,6 +181,7 @@ static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb,
 				struct l2t_entry *e)
 {
 	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(csk->cdev);
+	int t4 = is_t4(lldi->adapter_type);
 	int wscale = cxgbi_sock_compute_wscale(csk->mss_idx);
 	unsigned long long opt0;
 	unsigned int opt2;
@@ -248,6 +251,97 @@ static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb,
 	}
 
 	set_wr_txq(skb, CPL_PRIORITY_SETUP, csk->port_id);
+
+	pr_info_ipaddr("t%d csk 0x%p,%u,0x%lx,%u, rss_qid %u.\n",
+		       (&csk->saddr), (&csk->daddr), t4 ? 4 : 5, csk,
+		       csk->state, csk->flags, csk->atid, csk->rss_qid);
+
+	cxgb4_l2t_send(csk->cdev->ports[csk->port_id], skb, csk->l2t);
+}
+
+static void send_act_open_req6(struct cxgbi_sock *csk, struct sk_buff *skb,
+			       struct l2t_entry *e)
+{
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(csk->cdev);
+	int t4 = is_t4(lldi->adapter_type);
+	int wscale = cxgbi_sock_compute_wscale(csk->mss_idx);
+	unsigned long long opt0;
+	unsigned int opt2;
+	unsigned int qid_atid = ((unsigned int)csk->atid) |
+				 (((unsigned int)csk->rss_qid) << 14);
+
+	opt0 = KEEP_ALIVE(1) |
+		WND_SCALE(wscale) |
+		MSS_IDX(csk->mss_idx) |
+		L2T_IDX(((struct l2t_entry *)csk->l2t)->idx) |
+		TX_CHAN(csk->tx_chan) |
+		SMAC_SEL(csk->smac_idx) |
+		ULP_MODE(ULP_MODE_ISCSI) |
+		RCV_BUFSIZ(cxgb4i_rcv_win >> 10);
+
+	opt2 = RX_CHANNEL(0) |
+		RSS_QUEUE_VALID |
+		RX_FC_DISABLE |
+		RSS_QUEUE(csk->rss_qid);
+
+	if (t4) {
+		struct cpl_act_open_req6 *req =
+			    (struct cpl_act_open_req6 *)skb->head;
+
+		INIT_TP_WR(req, 0);
+		OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,
+							    qid_atid));
+		req->local_port = csk->saddr6.sin6_port;
+		req->peer_port = csk->daddr6.sin6_port;
+
+		req->local_ip_hi = *(__be64 *)(csk->saddr6.sin6_addr.s6_addr);
+		req->local_ip_lo = *(__be64 *)(csk->saddr6.sin6_addr.s6_addr +
+								    8);
+		req->peer_ip_hi = *(__be64 *)(csk->daddr6.sin6_addr.s6_addr);
+		req->peer_ip_lo = *(__be64 *)(csk->daddr6.sin6_addr.s6_addr +
+								    8);
+
+		req->opt0 = cpu_to_be64(opt0);
+
+		opt2 |= RX_FC_VALID;
+		req->opt2 = cpu_to_be32(opt2);
+
+		req->params = cpu_to_be32(cxgb4_select_ntuple(
+					  csk->cdev->ports[csk->port_id],
+					  csk->l2t));
+	} else {
+		struct cpl_t5_act_open_req6 *req =
+				(struct cpl_t5_act_open_req6 *)skb->head;
+
+		INIT_TP_WR(req, 0);
+		OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,
+							    qid_atid));
+		req->local_port = csk->saddr6.sin6_port;
+		req->peer_port = csk->daddr6.sin6_port;
+		req->local_ip_hi = *(__be64 *)(csk->saddr6.sin6_addr.s6_addr);
+		req->local_ip_lo = *(__be64 *)(csk->saddr6.sin6_addr.s6_addr +
+									8);
+		req->peer_ip_hi = *(__be64 *)(csk->daddr6.sin6_addr.s6_addr);
+		req->peer_ip_lo = *(__be64 *)(csk->daddr6.sin6_addr.s6_addr +
+									8);
+		req->opt0 = cpu_to_be64(opt0);
+
+		opt2 |= T5_OPT_2_VALID;
+		req->opt2 = cpu_to_be32(opt2);
+
+		req->params = cpu_to_be64(V_FILTER_TUPLE(cxgb4_select_ntuple(
+					  csk->cdev->ports[csk->port_id],
+					  csk->l2t)));
+	}
+
+	set_wr_txq(skb, CPL_PRIORITY_SETUP, csk->port_id);
+
+	pr_info("t%d csk 0x%p,%u,0x%lx,%u, [%pI6]:%u-[%pI6]:%u, rss_qid %u.\n",
+		t4 ? 4 : 5, csk, csk->state, csk->flags, csk->atid,
+		&csk->saddr6.sin6_addr, ntohs(csk->saddr.sin_port),
+		&csk->daddr6.sin6_addr, ntohs(csk->daddr.sin_port),
+		csk->rss_qid);
+
 	cxgb4_l2t_send(csk->cdev->ports[csk->port_id], skb, csk->l2t);
 }
 
@@ -586,9 +680,11 @@ static void do_act_establish(struct cxgbi_device *cdev, struct sk_buff *skb)
 		goto rel_skb;
 	}
 
-	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
-		"csk 0x%p,%u,0x%lx, tid %u, atid %u, rseq %u.\n",
-		csk, csk->state, csk->flags, tid, atid, rcv_isn);
+	pr_info_ipaddr("atid 0x%x, tid 0x%x, csk 0x%p,%u,0x%lx, isn %u.\n",
+		       (&csk->saddr), (&csk->daddr),
+		       atid, tid, csk, csk->state, csk->flags, rcv_isn);
+
+	module_put(THIS_MODULE);
 
 	cxgbi_sock_get(csk);
 	csk->tid = tid;
@@ -663,6 +759,9 @@ static void csk_act_open_retry_timer(unsigned long data)
 	struct sk_buff *skb;
 	struct cxgbi_sock *csk = (struct cxgbi_sock *)data;
 	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(csk->cdev);
+	void (*send_act_open_func)(struct cxgbi_sock *, struct sk_buff *,
+				   struct l2t_entry *);
+	int t4 = is_t4(lldi->adapter_type), size, size6;
 
 	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
 		"csk 0x%p,%u,0x%lx,%u.\n",
@@ -670,20 +769,35 @@ static void csk_act_open_retry_timer(unsigned long data)
 
 	cxgbi_sock_get(csk);
 	spin_lock_bh(&csk->lock);
-	skb = alloc_wr(is_t4(lldi->adapter_type) ?
-				sizeof(struct cpl_act_open_req) :
-				sizeof(struct cpl_t5_act_open_req),
-			0, GFP_ATOMIC);
+
+	if (t4) {
+		size = sizeof(struct cpl_act_open_req);
+		size6 = sizeof(struct cpl_act_open_req6);
+	} else {
+		size = sizeof(struct cpl_t5_act_open_req);
+		size6 = sizeof(struct cpl_t5_act_open_req6);
+	}
+
+	if (csk->csk_family == AF_INET) {
+		send_act_open_func = send_act_open_req;
+		skb = alloc_wr(size, 0, GFP_ATOMIC);
+	} else {
+		send_act_open_func = send_act_open_req6;
+		skb = alloc_wr(size6, 0, GFP_ATOMIC);
+	}
+
 	if (!skb)
 		cxgbi_sock_fail_act_open(csk, -ENOMEM);
 	else {
 		skb->sk = (struct sock *)csk;
 		t4_set_arp_err_handler(skb, csk,
-					cxgbi_sock_act_open_req_arp_failure);
-		send_act_open_req(csk, skb, csk->l2t);
+				       cxgbi_sock_act_open_req_arp_failure);
+		send_act_open_func(csk, skb, csk->l2t);
 	}
+
 	spin_unlock_bh(&csk->lock);
 	cxgbi_sock_put(csk);
+
 }
 
 static void do_act_open_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
@@ -703,10 +817,9 @@ static void do_act_open_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
 		goto rel_skb;
 	}
 
-	pr_info("%pI4:%u-%pI4:%u, atid %u,%u, status %u, csk 0x%p,%u,0x%lx.\n",
-		&csk->saddr.sin_addr.s_addr, ntohs(csk->saddr.sin_port),
-		&csk->daddr.sin_addr.s_addr, ntohs(csk->daddr.sin_port),
-		atid, tid, status, csk, csk->state, csk->flags);
+	pr_info_ipaddr("tid %u/%u, status %u.\n"
+		       "csk 0x%p,%u,0x%lx. ", (&csk->saddr), (&csk->daddr),
+		       atid, tid, status, csk, csk->state, csk->flags);
 
 	if (status == CPL_ERR_RTX_NEG_ADVICE)
 		goto rel_skb;
@@ -746,9 +859,9 @@ static void do_peer_close(struct cxgbi_device *cdev, struct sk_buff *skb)
 		pr_err("can't find connection for tid %u.\n", tid);
 		goto rel_skb;
 	}
-	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
-		"csk 0x%p,%u,0x%lx,%u.\n",
-		csk, csk->state, csk->flags, csk->tid);
+	pr_info_ipaddr("csk 0x%p,%u,0x%lx,%u.\n",
+		       (&csk->saddr), (&csk->daddr),
+		       csk, csk->state, csk->flags, csk->tid);
 	cxgbi_sock_rcv_peer_close(csk);
 rel_skb:
 	__kfree_skb(skb);
@@ -767,9 +880,9 @@ static void do_close_con_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
 		pr_err("can't find connection for tid %u.\n", tid);
 		goto rel_skb;
 	}
-	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
-		"csk 0x%p,%u,0x%lx,%u.\n",
-		csk, csk->state, csk->flags, csk->tid);
+	pr_info_ipaddr("csk 0x%p,%u,0x%lx,%u.\n",
+		       (&csk->saddr), (&csk->daddr),
+		       csk, csk->state, csk->flags, csk->tid);
 	cxgbi_sock_rcv_close_conn_rpl(csk, ntohl(rpl->snd_nxt));
 rel_skb:
 	__kfree_skb(skb);
@@ -808,9 +921,9 @@ static void do_abort_req_rss(struct cxgbi_device *cdev, struct sk_buff *skb)
 		goto rel_skb;
 	}
 
-	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
-		"csk 0x%p,%u,0x%lx, tid %u, status 0x%x.\n",
-		csk, csk->state, csk->flags, csk->tid, req->status);
+	pr_info_ipaddr("csk 0x%p,%u,0x%lx,%u, status %u.\n",
+		       (&csk->saddr), (&csk->daddr),
+		       csk, csk->state, csk->flags, csk->tid, req->status);
 
 	if (req->status == CPL_ERR_RTX_NEG_ADVICE ||
 	    req->status == CPL_ERR_PERSIST_NEG_ADVICE)
@@ -851,10 +964,10 @@ static void do_abort_rpl_rss(struct cxgbi_device *cdev, struct sk_buff *skb)
 	if (!csk)
 		goto rel_skb;
 
-	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
-		"status 0x%x, csk 0x%p, s %u, 0x%lx.\n",
-		rpl->status, csk, csk ? csk->state : 0,
-		csk ? csk->flags : 0UL);
+	if (csk)
+		pr_info_ipaddr("csk 0x%p,%u,0x%lx,%u, status %u.\n",
+			       (&csk->saddr), (&csk->daddr), csk,
+			       csk->state, csk->flags, csk->tid, rpl->status);
 
 	if (rpl->status == CPL_ERR_ABORT_FAILED)
 		goto rel_skb;
@@ -1163,15 +1276,29 @@ static int init_act_open(struct cxgbi_sock *csk)
 	struct cxgbi_device *cdev = csk->cdev;
 	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
 	struct net_device *ndev = cdev->ports[csk->port_id];
-	struct port_info *pi = netdev_priv(ndev);
 	struct sk_buff *skb = NULL;
-	struct neighbour *n;
+	struct neighbour *n = NULL;
+	void *daddr;
 	unsigned int step;
+	unsigned int size, size6;
+	int t4 = is_t4(lldi->adapter_type);
 
 	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
 		"csk 0x%p,%u,0x%lx,%u.\n",
 		csk, csk->state, csk->flags, csk->tid);
 
+	if (csk->csk_family == AF_INET)
+		daddr = &csk->daddr.sin_addr.s_addr;
+	else
+		daddr = &csk->daddr6.sin6_addr;
+
+	n = dst_neigh_lookup(csk->dst, daddr);
+
+	if (!n) {
+		pr_err("%s, can't get neighbour of csk->dst.\n", ndev->name);
+		goto rel_resource;
+	}
+
 	csk->atid = cxgb4_alloc_atid(lldi->tids, csk);
 	if (csk->atid < 0) {
 		pr_err("%s, NO atid available.\n", ndev->name);
@@ -1192,10 +1319,19 @@ static int init_act_open(struct cxgbi_sock *csk)
 	}
 	cxgbi_sock_get(csk);
 
-	skb = alloc_wr(is_t4(lldi->adapter_type) ?
-				sizeof(struct cpl_act_open_req) :
-				sizeof(struct cpl_t5_act_open_req),
-			0, GFP_ATOMIC);
+	if (t4) {
+		size = sizeof(struct cpl_act_open_req);
+		size6 = sizeof(struct cpl_act_open_req6);
+	} else {
+		size = sizeof(struct cpl_t5_act_open_req);
+		size6 = sizeof(struct cpl_t5_act_open_req6);
+	}
+
+	if (csk->csk_family == AF_INET)
+		skb = alloc_wr(size, 0, GFP_NOIO);
+	else
+		skb = alloc_wr(size6, 0, GFP_NOIO);
+
 	if (!skb)
 		goto rel_resource;
 	skb->sk = (struct sock *)csk;
@@ -1211,19 +1347,27 @@ static int init_act_open(struct cxgbi_sock *csk)
 	csk->txq_idx = cxgb4_port_idx(ndev) * step;
 	step = lldi->nrxq / lldi->nchan;
 	csk->rss_qid = lldi->rxq_ids[cxgb4_port_idx(ndev) * step];
-	csk->wr_max_cred = csk->wr_cred = lldi->wr_cred;
+	csk->wr_cred = lldi->wr_cred -
+		       DIV_ROUND_UP(sizeof(struct cpl_abort_req), 16);
+	csk->wr_max_cred = csk->wr_cred;
 	csk->wr_una_cred = 0;
 	cxgbi_sock_reset_wr_list(csk);
 	csk->err = 0;
-	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
-		"csk 0x%p,p%d,%s, %u,%u,%u, mss %u,%u, smac %u.\n",
-		csk, pi->port_id, ndev->name, csk->tx_chan,
-		csk->txq_idx, csk->rss_qid, csk->mtu, csk->mss_idx,
-		csk->smac_idx);
 
+	pr_info_ipaddr("csk 0x%p,%u,0x%lx,%u,%u,%u, mtu %u,%u, smac %u.\n",
+		       (&csk->saddr), (&csk->daddr), csk, csk->state,
+		       csk->flags, csk->tx_chan, csk->txq_idx, csk->rss_qid,
+		       csk->mtu, csk->mss_idx, csk->smac_idx);
+
+	/* must wait for either a act_open_rpl or act_open_establish */
+	try_module_get(THIS_MODULE);
 	cxgbi_sock_set_state(csk, CTP_ACTIVE_OPEN);
-	send_act_open_req(csk, skb, csk->l2t);
+	if (csk->csk_family == AF_INET)
+		send_act_open_req(csk, skb, csk->l2t);
+	else
+		send_act_open_req6(csk, skb, csk->l2t);
 	neigh_release(n);
+
 	return 0;
 
 rel_resource:
@@ -1487,6 +1631,131 @@ static int cxgb4i_ddp_init(struct cxgbi_device *cdev)
 	return 0;
 }
 
+static int cxgbi_inet6addr_handler(struct notifier_block *this,
+				   unsigned long event, void *data)
+{
+	struct inet6_ifaddr *ifa = data;
+	struct net_device *event_dev = ifa->idev->dev;
+	struct cxgbi_device *cdev;
+	int ret = NOTIFY_DONE;
+
+	rcu_read_lock();
+
+	if (event_dev->priv_flags & IFF_802_1Q_VLAN)
+		event_dev = vlan_dev_real_dev(event_dev);
+
+	cdev = cxgbi_device_find_by_netdev(event_dev, NULL);
+	if (!cdev) {
+		rcu_read_unlock();
+		return ret;
+	}
+	switch (event) {
+	case NETDEV_UP:
+		ret = cxgb4_clip_get(event_dev,
+				     (const struct in6_addr *)
+				     ((ifa)->addr.s6_addr));
+		if (ret < 0) {
+			rcu_read_unlock();
+			return ret;
+		}
+		ret = NOTIFY_OK;
+		break;
+
+	case NETDEV_DOWN:
+		cxgb4_clip_release(event_dev,
+				   (const struct in6_addr *)
+				   ((ifa)->addr.s6_addr));
+		ret = NOTIFY_OK;
+		break;
+
+	default:
+		break;
+	}
+
+	rcu_read_unlock();
+	return ret;
+}
+
+static struct notifier_block cxgbi_inet6addr_notifier = {
+	.notifier_call = cxgbi_inet6addr_handler
+};
+
+/* Retrieve IPv6 addresses from a root device (bond, vlan) associated with
+ * a physical device.
+ * The physical device reference is needed to send the actual CLIP command.
+ */
+static int update_dev_clip(struct net_device *root_dev, struct net_device *dev)
+{
+	struct inet6_dev *idev = NULL;
+	struct inet6_ifaddr *ifa;
+	int ret = 0;
+
+	idev = __in6_dev_get(root_dev);
+	if (!idev)
+		return ret;
+
+	read_lock_bh(&idev->lock);
+	list_for_each_entry(ifa, &idev->addr_list, if_list) {
+		pr_info("updating the clip for addr %pI6\n",
+			ifa->addr.s6_addr);
+		ret = cxgb4_clip_get(dev, (const struct in6_addr *)
+				     ifa->addr.s6_addr);
+		if (ret < 0)
+			break;
+	}
+
+	read_unlock_bh(&idev->lock);
+	return ret;
+}
+
+static int update_root_dev_clip(struct net_device *dev)
+{
+	struct net_device *root_dev = NULL;
+	int i, ret = 0;
+
+	/* First populate the real net device's IPv6 address */
+	ret = update_dev_clip(dev, dev);
+	if (ret)
+		return ret;
+
+	/* Parse all bond and vlan devices layered on top of the physical dev */
+	root_dev = netdev_master_upper_dev_get(dev);
+	if (root_dev) {
+		ret = update_dev_clip(root_dev, dev);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < VLAN_N_VID; i++) {
+		root_dev = __vlan_find_dev_deep_rcu(dev, htons(ETH_P_8021Q), i);
+		if (!root_dev)
+			continue;
+
+		ret = update_dev_clip(root_dev, dev);
+		if (ret)
+			break;
+	}
+	return ret;
+}
+
+static void cxgbi_update_clip(struct cxgbi_device *cdev)
+{
+	int i;
+
+	rcu_read_lock();
+
+	for (i = 0; i < cdev->nports; i++) {
+		struct net_device *dev = cdev->ports[i];
+		int ret = 0;
+
+		if (dev)
+			ret = update_root_dev_clip(dev);
+		if (ret < 0)
+			break;
+	}
+	rcu_read_unlock();
+}
+
 static void *t4_uld_add(const struct cxgb4_lld_info *lldi)
 {
 	struct cxgbi_device *cdev;
@@ -1605,6 +1874,7 @@ static int t4_uld_state_change(void *handle, enum cxgb4_state state)
 	switch (state) {
 	case CXGB4_STATE_UP:
 		pr_info("cdev 0x%p, UP.\n", cdev);
+		cxgbi_update_clip(cdev);
 		/* re-initialize */
 		break;
 	case CXGB4_STATE_START_RECOVERY:
@@ -1635,11 +1905,16 @@ static int __init cxgb4i_init_module(void)
 	if (rc < 0)
 		return rc;
 	cxgb4_register_uld(CXGB4_ULD_ISCSI, &cxgb4i_uld_info);
+
+	register_inet6addr_notifier(&cxgbi_inet6addr_notifier);
+
 	return 0;
 }
 
 static void __exit cxgb4i_exit_module(void)
 {
+	unregister_inet6addr_notifier(&cxgbi_inet6addr_notifier);
+
 	cxgb4_unregister_uld(CXGB4_ULD_ISCSI);
 	cxgbi_device_unregister_all(CXGBI_FLAG_DEV_T4);
 	cxgbi_iscsi_cleanup(&cxgb4i_iscsi_transport, &cxgb4i_stt);
-- 
2.0.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next v2 0/4] cxgb4i: Add ipv6 support
       [not found] ` <1405581498-28092-1-git-send-email-anish-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
  2014-07-17  7:18   ` [PATCH net-next v2 1/4] cxgb4/iw_cxgb4: Move common defines to cxgb4 Anish Bhatt
  2014-07-17  7:18   ` [PATCH net-next v2 4/4] cxgb4i: Add ipv6 code to driver, call into libcxgbi ipv6 api Anish Bhatt
@ 2014-07-17 23:06   ` David Miller
  2 siblings, 0 replies; 6+ messages in thread
From: David Miller @ 2014-07-17 23:06 UTC (permalink / raw)
  To: anish-ut6Up61K2wZBDgjK7y7TUQ
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	linux-scsi-u79uwXL29TY76Z2rM5mHXA, roland-BHEL68pLQRGGvPXPguhicg,
	hch-wEGCiKHe2LqWVfeAwA7xHQ, michaelc-hcNo3dDEHLuVc3sceRu5cw,
	jbottomley-bzQdu9zFT3WakBO8gow8eQ, kxie-ut6Up61K2wZBDgjK7y7TUQ,
	leedom-ut6Up61K2wZBDgjK7y7TUQ, hariprasad-ut6Up61K2wZBDgjK7y7TUQ,
	swise-7bPotxP6k4+P2YhJcF5u+vpXobYPEAuW

From: Anish Bhatt <anish-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
Date: Thu, 17 Jul 2014 00:18:14 -0700

>    The following patchset add ipv6 support for the cxgb4i(iscsi) driver.
> 
> Patch 1 moves a define from the iw_cxgb4 to cxgb4 to prevent code duplication,
>  as it is used by cxgb4i and iw_cxgb4 both.
> Patch 2 exports symbols needed by cxgb4i for ipv6 support from cxgb4.
> Patch 3 & 4 deal with actual ipv6 code in libcxgbi/cxgb4i.
> 
> Submitting to net-next as changes were needed in cxgb4/iw_cxgb4, and submitting
> to scsi separately would break compilation, cc-ing scsi & rdma.
> 
> v2 : Cleanup macro that prints ip addresses by using %pIS in patch 3

Series applied, thanks.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2014-07-17 23:06 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-17  7:18 [PATCH net-next v2 0/4] cxgb4i: Add ipv6 support Anish Bhatt
2014-07-17  7:18 ` [PATCH net-next v2 2/4] cxgb4: Export symbols required by cxgb4i for ipv6 support and required defines Anish Bhatt
2014-07-17  7:18 ` [PATCH net-next v2 3/4] libcxgbi: Add ipv6 api to driver Anish Bhatt
     [not found] ` <1405581498-28092-1-git-send-email-anish-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
2014-07-17  7:18   ` [PATCH net-next v2 1/4] cxgb4/iw_cxgb4: Move common defines to cxgb4 Anish Bhatt
2014-07-17  7:18   ` [PATCH net-next v2 4/4] cxgb4i: Add ipv6 code to driver, call into libcxgbi ipv6 api Anish Bhatt
2014-07-17 23:06   ` [PATCH net-next v2 0/4] cxgb4i: Add ipv6 support David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.