aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c3
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i.h1
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_iscsi.c25
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_offload.c23
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_offload.h3
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c51
-rw-r--r--include/scsi/iscsi_if.h7
-rw-r--r--include/scsi/scsi_transport_iscsi.h3
8 files changed, 87 insertions, 29 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 75223f50de58..ffbe0c76bc11 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -517,7 +517,8 @@ iscsi_iser_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *s
517} 517}
518 518
519static struct iscsi_endpoint * 519static struct iscsi_endpoint *
520iscsi_iser_ep_connect(struct sockaddr *dst_addr, int non_blocking) 520iscsi_iser_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
521 int non_blocking)
521{ 522{
522 int err; 523 int err;
523 struct iser_conn *ib_conn; 524 struct iser_conn *ib_conn;
diff --git a/drivers/scsi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgb3i/cxgb3i.h
index 59b0958d2d11..e3133b58e594 100644
--- a/drivers/scsi/cxgb3i/cxgb3i.h
+++ b/drivers/scsi/cxgb3i/cxgb3i.h
@@ -144,7 +144,6 @@ struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct t3cdev *);
144void cxgb3i_adapter_open(struct t3cdev *); 144void cxgb3i_adapter_open(struct t3cdev *);
145void cxgb3i_adapter_close(struct t3cdev *); 145void cxgb3i_adapter_close(struct t3cdev *);
146 146
147struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *);
148struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *, 147struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *,
149 struct net_device *); 148 struct net_device *);
150void cxgb3i_hba_host_remove(struct cxgb3i_hba *); 149void cxgb3i_hba_host_remove(struct cxgb3i_hba *);
diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
index 9212400b9b13..04a43744aedf 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
@@ -178,7 +178,7 @@ void cxgb3i_adapter_close(struct t3cdev *t3dev)
178 * cxgb3i_hba_find_by_netdev - find the cxgb3i_hba structure via net_device 178 * cxgb3i_hba_find_by_netdev - find the cxgb3i_hba structure via net_device
179 * @t3dev: t3cdev adapter 179 * @t3dev: t3cdev adapter
180 */ 180 */
181struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev) 181static struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev)
182{ 182{
183 struct cxgb3i_adapter *snic; 183 struct cxgb3i_adapter *snic;
184 int i; 184 int i;
@@ -261,20 +261,27 @@ void cxgb3i_hba_host_remove(struct cxgb3i_hba *hba)
261 261
262/** 262/**
263 * cxgb3i_ep_connect - establish TCP connection to target portal 263 * cxgb3i_ep_connect - establish TCP connection to target portal
264 * @shost: scsi host to use
264 * @dst_addr: target IP address 265 * @dst_addr: target IP address
265 * @non_blocking: blocking or non-blocking call 266 * @non_blocking: blocking or non-blocking call
266 * 267 *
267 * Initiates a TCP/IP connection to the dst_addr 268 * Initiates a TCP/IP connection to the dst_addr
268 */ 269 */
269static struct iscsi_endpoint *cxgb3i_ep_connect(struct sockaddr *dst_addr, 270static struct iscsi_endpoint *cxgb3i_ep_connect(struct Scsi_Host *shost,
271 struct sockaddr *dst_addr,
270 int non_blocking) 272 int non_blocking)
271{ 273{
272 struct iscsi_endpoint *ep; 274 struct iscsi_endpoint *ep;
273 struct cxgb3i_endpoint *cep; 275 struct cxgb3i_endpoint *cep;
274 struct cxgb3i_hba *hba; 276 struct cxgb3i_hba *hba = NULL;
275 struct s3_conn *c3cn = NULL; 277 struct s3_conn *c3cn = NULL;
276 int err = 0; 278 int err = 0;
277 279
280 if (shost)
281 hba = iscsi_host_priv(shost);
282
283 cxgb3i_api_debug("shost 0x%p, hba 0x%p.\n", shost, hba);
284
278 c3cn = cxgb3i_c3cn_create(); 285 c3cn = cxgb3i_c3cn_create();
279 if (!c3cn) { 286 if (!c3cn) {
280 cxgb3i_log_info("ep connect OOM.\n"); 287 cxgb3i_log_info("ep connect OOM.\n");
@@ -282,17 +289,27 @@ static struct iscsi_endpoint *cxgb3i_ep_connect(struct sockaddr *dst_addr,
282 goto release_conn; 289 goto release_conn;
283 } 290 }
284 291
285 err = cxgb3i_c3cn_connect(c3cn, (struct sockaddr_in *)dst_addr); 292 err = cxgb3i_c3cn_connect(hba ? hba->ndev : NULL, c3cn,
293 (struct sockaddr_in *)dst_addr);
286 if (err < 0) { 294 if (err < 0) {
287 cxgb3i_log_info("ep connect failed.\n"); 295 cxgb3i_log_info("ep connect failed.\n");
288 goto release_conn; 296 goto release_conn;
289 } 297 }
298
290 hba = cxgb3i_hba_find_by_netdev(c3cn->dst_cache->dev); 299 hba = cxgb3i_hba_find_by_netdev(c3cn->dst_cache->dev);
291 if (!hba) { 300 if (!hba) {
292 err = -ENOSPC; 301 err = -ENOSPC;
293 cxgb3i_log_info("NOT going through cxgbi device.\n"); 302 cxgb3i_log_info("NOT going through cxgbi device.\n");
294 goto release_conn; 303 goto release_conn;
295 } 304 }
305
306 if (shost && hba != iscsi_host_priv(shost)) {
307 err = -ENOSPC;
308 cxgb3i_log_info("Could not connect through request host%u\n",
309 shost->host_no);
310 goto release_conn;
311 }
312
296 if (c3cn_is_closing(c3cn)) { 313 if (c3cn_is_closing(c3cn)) {
297 err = -ENOSPC; 314 err = -ENOSPC;
298 cxgb3i_log_info("ep connect unable to connect.\n"); 315 cxgb3i_log_info("ep connect unable to connect.\n");
diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c
index e11c9c180f39..c1d5be4adf9c 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_offload.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_offload.c
@@ -1479,12 +1479,13 @@ static struct net_device *cxgb3_egress_dev(struct net_device *root_dev,
1479 return NULL; 1479 return NULL;
1480} 1480}
1481 1481
1482static struct rtable *find_route(__be32 saddr, __be32 daddr, 1482static struct rtable *find_route(struct net_device *dev,
1483 __be32 saddr, __be32 daddr,
1483 __be16 sport, __be16 dport) 1484 __be16 sport, __be16 dport)
1484{ 1485{
1485 struct rtable *rt; 1486 struct rtable *rt;
1486 struct flowi fl = { 1487 struct flowi fl = {
1487 .oif = 0, 1488 .oif = dev ? dev->ifindex : 0,
1488 .nl_u = { 1489 .nl_u = {
1489 .ip4_u = { 1490 .ip4_u = {
1490 .daddr = daddr, 1491 .daddr = daddr,
@@ -1573,36 +1574,40 @@ out_err:
1573 * 1574 *
1574 * return 0 if active open request is sent, < 0 otherwise. 1575 * return 0 if active open request is sent, < 0 otherwise.
1575 */ 1576 */
1576int cxgb3i_c3cn_connect(struct s3_conn *c3cn, struct sockaddr_in *usin) 1577int cxgb3i_c3cn_connect(struct net_device *dev, struct s3_conn *c3cn,
1578 struct sockaddr_in *usin)
1577{ 1579{
1578 struct rtable *rt; 1580 struct rtable *rt;
1579 struct net_device *dev;
1580 struct cxgb3i_sdev_data *cdata; 1581 struct cxgb3i_sdev_data *cdata;
1581 struct t3cdev *cdev; 1582 struct t3cdev *cdev;
1582 __be32 sipv4; 1583 __be32 sipv4;
1583 int err; 1584 int err;
1584 1585
1586 c3cn_conn_debug("c3cn 0x%p, dev 0x%p.\n", c3cn, dev);
1587
1585 if (usin->sin_family != AF_INET) 1588 if (usin->sin_family != AF_INET)
1586 return -EAFNOSUPPORT; 1589 return -EAFNOSUPPORT;
1587 1590
1588 c3cn->daddr.sin_port = usin->sin_port; 1591 c3cn->daddr.sin_port = usin->sin_port;
1589 c3cn->daddr.sin_addr.s_addr = usin->sin_addr.s_addr; 1592 c3cn->daddr.sin_addr.s_addr = usin->sin_addr.s_addr;
1590 1593
1591 rt = find_route(c3cn->saddr.sin_addr.s_addr, 1594 rt = find_route(dev, c3cn->saddr.sin_addr.s_addr,
1592 c3cn->daddr.sin_addr.s_addr, 1595 c3cn->daddr.sin_addr.s_addr,
1593 c3cn->saddr.sin_port, 1596 c3cn->saddr.sin_port,
1594 c3cn->daddr.sin_port); 1597 c3cn->daddr.sin_port);
1595 if (rt == NULL) { 1598 if (rt == NULL) {
1596 c3cn_conn_debug("NO route to 0x%x, port %u.\n", 1599 c3cn_conn_debug("NO route to 0x%x, port %u, dev %s.\n",
1597 c3cn->daddr.sin_addr.s_addr, 1600 c3cn->daddr.sin_addr.s_addr,
1598 ntohs(c3cn->daddr.sin_port)); 1601 ntohs(c3cn->daddr.sin_port),
1602 dev ? dev->name : "any");
1599 return -ENETUNREACH; 1603 return -ENETUNREACH;
1600 } 1604 }
1601 1605
1602 if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) { 1606 if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
1603 c3cn_conn_debug("multi-cast route to 0x%x, port %u.\n", 1607 c3cn_conn_debug("multi-cast route to 0x%x, port %u, dev %s.\n",
1604 c3cn->daddr.sin_addr.s_addr, 1608 c3cn->daddr.sin_addr.s_addr,
1605 ntohs(c3cn->daddr.sin_port)); 1609 ntohs(c3cn->daddr.sin_port),
1610 dev ? dev->name : "any");
1606 ip_rt_put(rt); 1611 ip_rt_put(rt);
1607 return -ENETUNREACH; 1612 return -ENETUNREACH;
1608 } 1613 }
diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.h b/drivers/scsi/cxgb3i/cxgb3i_offload.h
index ebfca960c0a9..6a1d86b1fafe 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_offload.h
+++ b/drivers/scsi/cxgb3i/cxgb3i_offload.h
@@ -169,7 +169,8 @@ void cxgb3i_sdev_add(struct t3cdev *, struct cxgb3_client *);
169void cxgb3i_sdev_remove(struct t3cdev *); 169void cxgb3i_sdev_remove(struct t3cdev *);
170 170
171struct s3_conn *cxgb3i_c3cn_create(void); 171struct s3_conn *cxgb3i_c3cn_create(void);
172int cxgb3i_c3cn_connect(struct s3_conn *, struct sockaddr_in *); 172int cxgb3i_c3cn_connect(struct net_device *, struct s3_conn *,
173 struct sockaddr_in *);
173void cxgb3i_c3cn_rx_credits(struct s3_conn *, int); 174void cxgb3i_c3cn_rx_credits(struct s3_conn *, int);
174int cxgb3i_c3cn_send_pdus(struct s3_conn *, struct sk_buff *); 175int cxgb3i_c3cn_send_pdus(struct s3_conn *, struct sk_buff *);
175void cxgb3i_c3cn_release(struct s3_conn *); 176void cxgb3i_c3cn_release(struct s3_conn *);
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 0a2ce7b6325c..d69a53aa406f 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -1268,26 +1268,54 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
1268 return err; 1268 return err;
1269} 1269}
1270 1270
1271static int iscsi_if_ep_connect(struct iscsi_transport *transport,
1272 struct iscsi_uevent *ev, int msg_type)
1273{
1274 struct iscsi_endpoint *ep;
1275 struct sockaddr *dst_addr;
1276 struct Scsi_Host *shost = NULL;
1277 int non_blocking, err = 0;
1278
1279 if (!transport->ep_connect)
1280 return -EINVAL;
1281
1282 if (msg_type == ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST) {
1283 shost = scsi_host_lookup(ev->u.ep_connect_through_host.host_no);
1284 if (!shost) {
1285 printk(KERN_ERR "ep connect failed. Could not find "
1286 "host no %u\n",
1287 ev->u.ep_connect_through_host.host_no);
1288 return -ENODEV;
1289 }
1290 non_blocking = ev->u.ep_connect_through_host.non_blocking;
1291 } else
1292 non_blocking = ev->u.ep_connect.non_blocking;
1293
1294 dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
1295 ep = transport->ep_connect(shost, dst_addr, non_blocking);
1296 if (IS_ERR(ep)) {
1297 err = PTR_ERR(ep);
1298 goto release_host;
1299 }
1300
1301 ev->r.ep_connect_ret.handle = ep->id;
1302release_host:
1303 if (shost)
1304 scsi_host_put(shost);
1305 return err;
1306}
1307
1271static int 1308static int
1272iscsi_if_transport_ep(struct iscsi_transport *transport, 1309iscsi_if_transport_ep(struct iscsi_transport *transport,
1273 struct iscsi_uevent *ev, int msg_type) 1310 struct iscsi_uevent *ev, int msg_type)
1274{ 1311{
1275 struct iscsi_endpoint *ep; 1312 struct iscsi_endpoint *ep;
1276 struct sockaddr *dst_addr;
1277 int rc = 0; 1313 int rc = 0;
1278 1314
1279 switch (msg_type) { 1315 switch (msg_type) {
1316 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
1280 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT: 1317 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
1281 if (!transport->ep_connect) 1318 rc = iscsi_if_ep_connect(transport, ev, msg_type);
1282 return -EINVAL;
1283
1284 dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
1285 ep = transport->ep_connect(dst_addr,
1286 ev->u.ep_connect.non_blocking);
1287 if (IS_ERR(ep))
1288 return PTR_ERR(ep);
1289
1290 ev->r.ep_connect_ret.handle = ep->id;
1291 break; 1319 break;
1292 case ISCSI_UEVENT_TRANSPORT_EP_POLL: 1320 case ISCSI_UEVENT_TRANSPORT_EP_POLL:
1293 if (!transport->ep_poll) 1321 if (!transport->ep_poll)
@@ -1469,6 +1497,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1469 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT: 1497 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
1470 case ISCSI_UEVENT_TRANSPORT_EP_POLL: 1498 case ISCSI_UEVENT_TRANSPORT_EP_POLL:
1471 case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT: 1499 case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
1500 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
1472 err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type); 1501 err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type);
1473 break; 1502 break;
1474 case ISCSI_UEVENT_TGT_DSCVR: 1503 case ISCSI_UEVENT_TGT_DSCVR:
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index d0ed5226f8c4..2c1a4af9eafb 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -50,7 +50,8 @@ enum iscsi_uevent_e {
50 ISCSI_UEVENT_TGT_DSCVR = UEVENT_BASE + 15, 50 ISCSI_UEVENT_TGT_DSCVR = UEVENT_BASE + 15,
51 ISCSI_UEVENT_SET_HOST_PARAM = UEVENT_BASE + 16, 51 ISCSI_UEVENT_SET_HOST_PARAM = UEVENT_BASE + 16,
52 ISCSI_UEVENT_UNBIND_SESSION = UEVENT_BASE + 17, 52 ISCSI_UEVENT_UNBIND_SESSION = UEVENT_BASE + 17,
53 ISCSI_UEVENT_CREATE_BOUND_SESSION = UEVENT_BASE + 18, 53 ISCSI_UEVENT_CREATE_BOUND_SESSION = UEVENT_BASE + 18,
54 ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST = UEVENT_BASE + 19,
54 55
55 /* up events */ 56 /* up events */
56 ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1, 57 ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1,
@@ -131,6 +132,10 @@ struct iscsi_uevent {
131 struct msg_transport_connect { 132 struct msg_transport_connect {
132 uint32_t non_blocking; 133 uint32_t non_blocking;
133 } ep_connect; 134 } ep_connect;
135 struct msg_transport_connect_through_host {
136 uint32_t host_no;
137 uint32_t non_blocking;
138 } ep_connect_through_host;
134 struct msg_transport_poll { 139 struct msg_transport_poll {
135 uint64_t ep_handle; 140 uint64_t ep_handle;
136 uint32_t timeout_ms; 141 uint32_t timeout_ms;
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 457588e1119b..8cb7a31d9961 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -126,7 +126,8 @@ struct iscsi_transport {
126 int *index, int *age); 126 int *index, int *age);
127 127
128 void (*session_recovery_timedout) (struct iscsi_cls_session *session); 128 void (*session_recovery_timedout) (struct iscsi_cls_session *session);
129 struct iscsi_endpoint *(*ep_connect) (struct sockaddr *dst_addr, 129 struct iscsi_endpoint *(*ep_connect) (struct Scsi_Host *shost,
130 struct sockaddr *dst_addr,
130 int non_blocking); 131 int non_blocking);
131 int (*ep_poll) (struct iscsi_endpoint *ep, int timeout_ms); 132 int (*ep_poll) (struct iscsi_endpoint *ep, int timeout_ms);
132 void (*ep_disconnect) (struct iscsi_endpoint *ep); 133 void (*ep_disconnect) (struct iscsi_endpoint *ep);