diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/cxgb3i/cxgb3i_offload.c | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c index 26ffdcd5a437..15a00e8b7122 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_offload.c +++ b/drivers/scsi/cxgb3i/cxgb3i_offload.c | |||
@@ -1440,6 +1440,10 @@ void cxgb3i_c3cn_release(struct s3_conn *c3cn) | |||
1440 | static int is_cxgb3_dev(struct net_device *dev) | 1440 | static int is_cxgb3_dev(struct net_device *dev) |
1441 | { | 1441 | { |
1442 | struct cxgb3i_sdev_data *cdata; | 1442 | struct cxgb3i_sdev_data *cdata; |
1443 | struct net_device *ndev = dev; | ||
1444 | |||
1445 | if (dev->priv_flags & IFF_802_1Q_VLAN) | ||
1446 | ndev = vlan_dev_real_dev(dev); | ||
1443 | 1447 | ||
1444 | write_lock(&cdata_rwlock); | 1448 | write_lock(&cdata_rwlock); |
1445 | list_for_each_entry(cdata, &cdata_list, list) { | 1449 | list_for_each_entry(cdata, &cdata_list, list) { |
@@ -1447,7 +1451,7 @@ static int is_cxgb3_dev(struct net_device *dev) | |||
1447 | int i; | 1451 | int i; |
1448 | 1452 | ||
1449 | for (i = 0; i < ports->nports; i++) | 1453 | for (i = 0; i < ports->nports; i++) |
1450 | if (dev == ports->lldevs[i]) { | 1454 | if (ndev == ports->lldevs[i]) { |
1451 | write_unlock(&cdata_rwlock); | 1455 | write_unlock(&cdata_rwlock); |
1452 | return 1; | 1456 | return 1; |
1453 | } | 1457 | } |
@@ -1566,6 +1570,26 @@ out_err: | |||
1566 | return -EINVAL; | 1570 | return -EINVAL; |
1567 | } | 1571 | } |
1568 | 1572 | ||
1573 | /** | ||
1574 | * cxgb3i_find_dev - find the interface associated with the given address | ||
1575 | * @ipaddr: ip address | ||
1576 | */ | ||
1577 | static struct net_device * | ||
1578 | cxgb3i_find_dev(struct net_device *dev, __be32 ipaddr) | ||
1579 | { | ||
1580 | struct flowi fl; | ||
1581 | int err; | ||
1582 | struct rtable *rt; | ||
1583 | |||
1584 | memset(&fl, 0, sizeof(fl)); | ||
1585 | fl.nl_u.ip4_u.daddr = ipaddr; | ||
1586 | |||
1587 | err = ip_route_output_key(dev ? dev_net(dev) : &init_net, &rt, &fl); | ||
1588 | if (!err) | ||
1589 | return (&rt->u.dst)->dev; | ||
1590 | |||
1591 | return NULL; | ||
1592 | } | ||
1569 | 1593 | ||
1570 | /** | 1594 | /** |
1571 | * cxgb3i_c3cn_connect - initiates an iscsi tcp connection to a given address | 1595 | * cxgb3i_c3cn_connect - initiates an iscsi tcp connection to a given address |
@@ -1581,6 +1605,7 @@ int cxgb3i_c3cn_connect(struct net_device *dev, struct s3_conn *c3cn, | |||
1581 | struct cxgb3i_sdev_data *cdata; | 1605 | struct cxgb3i_sdev_data *cdata; |
1582 | struct t3cdev *cdev; | 1606 | struct t3cdev *cdev; |
1583 | __be32 sipv4; | 1607 | __be32 sipv4; |
1608 | struct net_device *dstdev; | ||
1584 | int err; | 1609 | int err; |
1585 | 1610 | ||
1586 | c3cn_conn_debug("c3cn 0x%p, dev 0x%p.\n", c3cn, dev); | 1611 | c3cn_conn_debug("c3cn 0x%p, dev 0x%p.\n", c3cn, dev); |
@@ -1591,6 +1616,13 @@ int cxgb3i_c3cn_connect(struct net_device *dev, struct s3_conn *c3cn, | |||
1591 | c3cn->daddr.sin_port = usin->sin_port; | 1616 | c3cn->daddr.sin_port = usin->sin_port; |
1592 | c3cn->daddr.sin_addr.s_addr = usin->sin_addr.s_addr; | 1617 | c3cn->daddr.sin_addr.s_addr = usin->sin_addr.s_addr; |
1593 | 1618 | ||
1619 | dstdev = cxgb3i_find_dev(dev, usin->sin_addr.s_addr); | ||
1620 | if (!dstdev || !is_cxgb3_dev(dstdev)) | ||
1621 | return -ENETUNREACH; | ||
1622 | |||
1623 | if (dstdev->priv_flags & IFF_802_1Q_VLAN) | ||
1624 | dev = dstdev; | ||
1625 | |||
1594 | rt = find_route(dev, c3cn->saddr.sin_addr.s_addr, | 1626 | rt = find_route(dev, c3cn->saddr.sin_addr.s_addr, |
1595 | c3cn->daddr.sin_addr.s_addr, | 1627 | c3cn->daddr.sin_addr.s_addr, |
1596 | c3cn->saddr.sin_port, | 1628 | c3cn->saddr.sin_port, |