diff options
Diffstat (limited to 'drivers/s390/net/qeth_l3_main.c')
-rw-r--r-- | drivers/s390/net/qeth_l3_main.c | 796 |
1 files changed, 388 insertions, 408 deletions
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index e22ae248f613..fd69da3fa6b4 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c | |||
@@ -30,6 +30,7 @@ | |||
30 | 30 | ||
31 | #include "qeth_l3.h" | 31 | #include "qeth_l3.h" |
32 | 32 | ||
33 | |||
33 | static int qeth_l3_set_offline(struct ccwgroup_device *); | 34 | static int qeth_l3_set_offline(struct ccwgroup_device *); |
34 | static int qeth_l3_recover(void *); | 35 | static int qeth_l3_recover(void *); |
35 | static int qeth_l3_stop(struct net_device *); | 36 | static int qeth_l3_stop(struct net_device *); |
@@ -42,33 +43,6 @@ static int qeth_l3_deregister_addr_entry(struct qeth_card *, | |||
42 | static int __qeth_l3_set_online(struct ccwgroup_device *, int); | 43 | static int __qeth_l3_set_online(struct ccwgroup_device *, int); |
43 | static int __qeth_l3_set_offline(struct ccwgroup_device *, int); | 44 | static int __qeth_l3_set_offline(struct ccwgroup_device *, int); |
44 | 45 | ||
45 | int qeth_l3_set_large_send(struct qeth_card *card, | ||
46 | enum qeth_large_send_types type) | ||
47 | { | ||
48 | int rc = 0; | ||
49 | |||
50 | card->options.large_send = type; | ||
51 | if (card->dev == NULL) | ||
52 | return 0; | ||
53 | |||
54 | if (card->options.large_send == QETH_LARGE_SEND_TSO) { | ||
55 | if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) { | ||
56 | card->dev->features |= NETIF_F_TSO | NETIF_F_SG | | ||
57 | NETIF_F_IP_CSUM; | ||
58 | } else { | ||
59 | card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | | ||
60 | NETIF_F_IP_CSUM); | ||
61 | card->options.large_send = QETH_LARGE_SEND_NO; | ||
62 | rc = -EOPNOTSUPP; | ||
63 | } | ||
64 | } else { | ||
65 | card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | | ||
66 | NETIF_F_IP_CSUM); | ||
67 | card->options.large_send = QETH_LARGE_SEND_NO; | ||
68 | } | ||
69 | return rc; | ||
70 | } | ||
71 | |||
72 | static int qeth_l3_isxdigit(char *buf) | 46 | static int qeth_l3_isxdigit(char *buf) |
73 | { | 47 | { |
74 | while (*buf) { | 48 | while (*buf) { |
@@ -103,12 +77,7 @@ int qeth_l3_string_to_ipaddr4(const char *buf, __u8 *addr) | |||
103 | 77 | ||
104 | void qeth_l3_ipaddr6_to_string(const __u8 *addr, char *buf) | 78 | void qeth_l3_ipaddr6_to_string(const __u8 *addr, char *buf) |
105 | { | 79 | { |
106 | sprintf(buf, "%02x%02x:%02x%02x:%02x%02x:%02x%02x" | 80 | sprintf(buf, "%pI6", addr); |
107 | ":%02x%02x:%02x%02x:%02x%02x:%02x%02x", | ||
108 | addr[0], addr[1], addr[2], addr[3], | ||
109 | addr[4], addr[5], addr[6], addr[7], | ||
110 | addr[8], addr[9], addr[10], addr[11], | ||
111 | addr[12], addr[13], addr[14], addr[15]); | ||
112 | } | 81 | } |
113 | 82 | ||
114 | int qeth_l3_string_to_ipaddr6(const char *buf, __u8 *addr) | 83 | int qeth_l3_string_to_ipaddr6(const char *buf, __u8 *addr) |
@@ -460,8 +429,11 @@ static void qeth_l3_set_ip_addr_list(struct qeth_card *card) | |||
460 | QETH_CARD_TEXT(card, 2, "sdiplist"); | 429 | QETH_CARD_TEXT(card, 2, "sdiplist"); |
461 | QETH_CARD_HEX(card, 2, &card, sizeof(void *)); | 430 | QETH_CARD_HEX(card, 2, &card, sizeof(void *)); |
462 | 431 | ||
463 | if (card->options.sniffer) | 432 | if ((card->state != CARD_STATE_UP && |
433 | card->state != CARD_STATE_SOFTSETUP) || card->options.sniffer) { | ||
464 | return; | 434 | return; |
435 | } | ||
436 | |||
465 | spin_lock_irqsave(&card->ip_lock, flags); | 437 | spin_lock_irqsave(&card->ip_lock, flags); |
466 | tbd_list = card->ip_tbd_list; | 438 | tbd_list = card->ip_tbd_list; |
467 | card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC); | 439 | card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC); |
@@ -511,8 +483,7 @@ static void qeth_l3_set_ip_addr_list(struct qeth_card *card) | |||
511 | kfree(tbd_list); | 483 | kfree(tbd_list); |
512 | } | 484 | } |
513 | 485 | ||
514 | static void qeth_l3_clear_ip_list(struct qeth_card *card, int clean, | 486 | static void qeth_l3_clear_ip_list(struct qeth_card *card, int recover) |
515 | int recover) | ||
516 | { | 487 | { |
517 | struct qeth_ipaddr *addr, *tmp; | 488 | struct qeth_ipaddr *addr, *tmp; |
518 | unsigned long flags; | 489 | unsigned long flags; |
@@ -531,11 +502,6 @@ static void qeth_l3_clear_ip_list(struct qeth_card *card, int clean, | |||
531 | addr = list_entry(card->ip_list.next, | 502 | addr = list_entry(card->ip_list.next, |
532 | struct qeth_ipaddr, entry); | 503 | struct qeth_ipaddr, entry); |
533 | list_del_init(&addr->entry); | 504 | list_del_init(&addr->entry); |
534 | if (clean) { | ||
535 | spin_unlock_irqrestore(&card->ip_lock, flags); | ||
536 | qeth_l3_deregister_addr_entry(card, addr); | ||
537 | spin_lock_irqsave(&card->ip_lock, flags); | ||
538 | } | ||
539 | if (!recover || addr->is_multicast) { | 505 | if (!recover || addr->is_multicast) { |
540 | kfree(addr); | 506 | kfree(addr); |
541 | continue; | 507 | continue; |
@@ -1311,39 +1277,6 @@ static int qeth_l3_start_ipa_multicast(struct qeth_card *card) | |||
1311 | return rc; | 1277 | return rc; |
1312 | } | 1278 | } |
1313 | 1279 | ||
1314 | static int qeth_l3_query_ipassists_cb(struct qeth_card *card, | ||
1315 | struct qeth_reply *reply, unsigned long data) | ||
1316 | { | ||
1317 | struct qeth_ipa_cmd *cmd; | ||
1318 | |||
1319 | QETH_DBF_TEXT(SETUP, 2, "qipasscb"); | ||
1320 | |||
1321 | cmd = (struct qeth_ipa_cmd *) data; | ||
1322 | if (cmd->hdr.prot_version == QETH_PROT_IPV4) { | ||
1323 | card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported; | ||
1324 | card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; | ||
1325 | } else { | ||
1326 | card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported; | ||
1327 | card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled; | ||
1328 | } | ||
1329 | QETH_DBF_TEXT(SETUP, 2, "suppenbl"); | ||
1330 | QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_supported); | ||
1331 | QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_enabled); | ||
1332 | return 0; | ||
1333 | } | ||
1334 | |||
1335 | static int qeth_l3_query_ipassists(struct qeth_card *card, | ||
1336 | enum qeth_prot_versions prot) | ||
1337 | { | ||
1338 | int rc; | ||
1339 | struct qeth_cmd_buffer *iob; | ||
1340 | |||
1341 | QETH_DBF_TEXT_(SETUP, 2, "qipassi%i", prot); | ||
1342 | iob = qeth_get_ipacmd_buffer(card, IPA_CMD_QIPASSIST, prot); | ||
1343 | rc = qeth_send_ipa_cmd(card, iob, qeth_l3_query_ipassists_cb, NULL); | ||
1344 | return rc; | ||
1345 | } | ||
1346 | |||
1347 | #ifdef CONFIG_QETH_IPV6 | 1280 | #ifdef CONFIG_QETH_IPV6 |
1348 | static int qeth_l3_softsetup_ipv6(struct qeth_card *card) | 1281 | static int qeth_l3_softsetup_ipv6(struct qeth_card *card) |
1349 | { | 1282 | { |
@@ -1354,7 +1287,7 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card) | |||
1354 | if (card->info.type == QETH_CARD_TYPE_IQD) | 1287 | if (card->info.type == QETH_CARD_TYPE_IQD) |
1355 | goto out; | 1288 | goto out; |
1356 | 1289 | ||
1357 | rc = qeth_l3_query_ipassists(card, QETH_PROT_IPV6); | 1290 | rc = qeth_query_ipassists(card, QETH_PROT_IPV6); |
1358 | if (rc) { | 1291 | if (rc) { |
1359 | dev_err(&card->gdev->dev, | 1292 | dev_err(&card->gdev->dev, |
1360 | "Activating IPv6 support for %s failed\n", | 1293 | "Activating IPv6 support for %s failed\n", |
@@ -1479,68 +1412,38 @@ static int qeth_l3_send_checksum_command(struct qeth_card *card) | |||
1479 | return 0; | 1412 | return 0; |
1480 | } | 1413 | } |
1481 | 1414 | ||
1482 | int qeth_l3_set_rx_csum(struct qeth_card *card, | 1415 | int qeth_l3_set_rx_csum(struct qeth_card *card, int on) |
1483 | enum qeth_checksum_types csum_type) | ||
1484 | { | 1416 | { |
1485 | int rc = 0; | 1417 | int rc = 0; |
1486 | 1418 | ||
1487 | if (card->options.checksum_type == HW_CHECKSUMMING) { | 1419 | if (on) { |
1488 | if ((csum_type != HW_CHECKSUMMING) && | 1420 | rc = qeth_l3_send_checksum_command(card); |
1489 | (card->state != CARD_STATE_DOWN)) { | 1421 | if (rc) |
1490 | rc = qeth_l3_send_simple_setassparms(card, | 1422 | return -EIO; |
1491 | IPA_INBOUND_CHECKSUM, IPA_CMD_ASS_STOP, 0); | 1423 | dev_info(&card->gdev->dev, |
1492 | if (rc) | 1424 | "HW Checksumming (inbound) enabled\n"); |
1493 | return -EIO; | ||
1494 | } | ||
1495 | } else { | 1425 | } else { |
1496 | if (csum_type == HW_CHECKSUMMING) { | 1426 | rc = qeth_l3_send_simple_setassparms(card, |
1497 | if (card->state != CARD_STATE_DOWN) { | 1427 | IPA_INBOUND_CHECKSUM, IPA_CMD_ASS_STOP, 0); |
1498 | if (!qeth_is_supported(card, | 1428 | if (rc) |
1499 | IPA_INBOUND_CHECKSUM)) | 1429 | return -EIO; |
1500 | return -EPERM; | ||
1501 | rc = qeth_l3_send_checksum_command(card); | ||
1502 | if (rc) | ||
1503 | return -EIO; | ||
1504 | } | ||
1505 | } | ||
1506 | } | 1430 | } |
1507 | card->options.checksum_type = csum_type; | 1431 | |
1508 | return rc; | 1432 | return 0; |
1509 | } | 1433 | } |
1510 | 1434 | ||
1511 | static int qeth_l3_start_ipa_checksum(struct qeth_card *card) | 1435 | static int qeth_l3_start_ipa_checksum(struct qeth_card *card) |
1512 | { | 1436 | { |
1513 | int rc = 0; | ||
1514 | |||
1515 | QETH_CARD_TEXT(card, 3, "strtcsum"); | 1437 | QETH_CARD_TEXT(card, 3, "strtcsum"); |
1516 | 1438 | ||
1517 | if (card->options.checksum_type == NO_CHECKSUMMING) { | 1439 | if (card->dev->features & NETIF_F_RXCSUM) { |
1518 | dev_info(&card->gdev->dev, | 1440 | rtnl_lock(); |
1519 | "Using no checksumming on %s.\n", | 1441 | /* force set_features call */ |
1520 | QETH_CARD_IFNAME(card)); | 1442 | card->dev->features &= ~NETIF_F_RXCSUM; |
1521 | return 0; | 1443 | netdev_update_features(card->dev); |
1522 | } | 1444 | rtnl_unlock(); |
1523 | if (card->options.checksum_type == SW_CHECKSUMMING) { | ||
1524 | dev_info(&card->gdev->dev, | ||
1525 | "Using SW checksumming on %s.\n", | ||
1526 | QETH_CARD_IFNAME(card)); | ||
1527 | return 0; | ||
1528 | } | ||
1529 | if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) { | ||
1530 | dev_info(&card->gdev->dev, | ||
1531 | "Inbound HW Checksumming not " | ||
1532 | "supported on %s,\ncontinuing " | ||
1533 | "using Inbound SW Checksumming\n", | ||
1534 | QETH_CARD_IFNAME(card)); | ||
1535 | card->options.checksum_type = SW_CHECKSUMMING; | ||
1536 | return 0; | ||
1537 | } | 1445 | } |
1538 | rc = qeth_l3_send_checksum_command(card); | 1446 | return 0; |
1539 | if (!rc) | ||
1540 | dev_info(&card->gdev->dev, | ||
1541 | "HW Checksumming (inbound) enabled\n"); | ||
1542 | |||
1543 | return rc; | ||
1544 | } | 1447 | } |
1545 | 1448 | ||
1546 | static int qeth_l3_start_ipa_tx_checksum(struct qeth_card *card) | 1449 | static int qeth_l3_start_ipa_tx_checksum(struct qeth_card *card) |
@@ -1587,10 +1490,8 @@ static int qeth_l3_start_ipa_tso(struct qeth_card *card) | |||
1587 | dev_info(&card->gdev->dev, | 1490 | dev_info(&card->gdev->dev, |
1588 | "Outbound TSO enabled\n"); | 1491 | "Outbound TSO enabled\n"); |
1589 | } | 1492 | } |
1590 | if (rc && (card->options.large_send == QETH_LARGE_SEND_TSO)) { | 1493 | if (rc) |
1591 | card->options.large_send = QETH_LARGE_SEND_NO; | 1494 | card->dev->features &= ~NETIF_F_TSO; |
1592 | card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG); | ||
1593 | } | ||
1594 | return rc; | 1495 | return rc; |
1595 | } | 1496 | } |
1596 | 1497 | ||
@@ -1612,29 +1513,6 @@ static int qeth_l3_start_ipassists(struct qeth_card *card) | |||
1612 | return 0; | 1513 | return 0; |
1613 | } | 1514 | } |
1614 | 1515 | ||
1615 | static int qeth_l3_put_unique_id(struct qeth_card *card) | ||
1616 | { | ||
1617 | |||
1618 | int rc = 0; | ||
1619 | struct qeth_cmd_buffer *iob; | ||
1620 | struct qeth_ipa_cmd *cmd; | ||
1621 | |||
1622 | QETH_CARD_TEXT(card, 2, "puniqeid"); | ||
1623 | |||
1624 | if ((card->info.unique_id & UNIQUE_ID_NOT_BY_CARD) == | ||
1625 | UNIQUE_ID_NOT_BY_CARD) | ||
1626 | return -1; | ||
1627 | iob = qeth_get_ipacmd_buffer(card, IPA_CMD_DESTROY_ADDR, | ||
1628 | QETH_PROT_IPV6); | ||
1629 | cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); | ||
1630 | *((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) = | ||
1631 | card->info.unique_id; | ||
1632 | memcpy(&cmd->data.create_destroy_addr.unique_id[0], | ||
1633 | card->dev->dev_addr, OSA_ADDR_LEN); | ||
1634 | rc = qeth_send_ipa_cmd(card, iob, NULL, NULL); | ||
1635 | return rc; | ||
1636 | } | ||
1637 | |||
1638 | static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card, | 1516 | static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card, |
1639 | struct qeth_reply *reply, unsigned long data) | 1517 | struct qeth_reply *reply, unsigned long data) |
1640 | { | 1518 | { |
@@ -1801,7 +1679,8 @@ static void qeth_l3_add_mc(struct qeth_card *card, struct in_device *in4_dev) | |||
1801 | char buf[MAX_ADDR_LEN]; | 1679 | char buf[MAX_ADDR_LEN]; |
1802 | 1680 | ||
1803 | QETH_CARD_TEXT(card, 4, "addmc"); | 1681 | QETH_CARD_TEXT(card, 4, "addmc"); |
1804 | for (im4 = in4_dev->mc_list; im4; im4 = im4->next) { | 1682 | for (im4 = rcu_dereference(in4_dev->mc_list); im4 != NULL; |
1683 | im4 = rcu_dereference(im4->next_rcu)) { | ||
1805 | qeth_l3_get_mac_for_ipm(im4->multiaddr, buf, in4_dev->dev); | 1684 | qeth_l3_get_mac_for_ipm(im4->multiaddr, buf, in4_dev->dev); |
1806 | ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV4); | 1685 | ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV4); |
1807 | if (!ipm) | 1686 | if (!ipm) |
@@ -1825,7 +1704,7 @@ static void qeth_l3_add_vlan_mc(struct qeth_card *card) | |||
1825 | return; | 1704 | return; |
1826 | 1705 | ||
1827 | vg = card->vlangrp; | 1706 | vg = card->vlangrp; |
1828 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 1707 | for (i = 0; i < VLAN_N_VID; i++) { |
1829 | struct net_device *netdev = vlan_group_get_device(vg, i); | 1708 | struct net_device *netdev = vlan_group_get_device(vg, i); |
1830 | if (netdev == NULL || | 1709 | if (netdev == NULL || |
1831 | !(netdev->flags & IFF_UP)) | 1710 | !(netdev->flags & IFF_UP)) |
@@ -1833,9 +1712,9 @@ static void qeth_l3_add_vlan_mc(struct qeth_card *card) | |||
1833 | in_dev = in_dev_get(netdev); | 1712 | in_dev = in_dev_get(netdev); |
1834 | if (!in_dev) | 1713 | if (!in_dev) |
1835 | continue; | 1714 | continue; |
1836 | read_lock(&in_dev->mc_list_lock); | 1715 | rcu_read_lock(); |
1837 | qeth_l3_add_mc(card, in_dev); | 1716 | qeth_l3_add_mc(card, in_dev); |
1838 | read_unlock(&in_dev->mc_list_lock); | 1717 | rcu_read_unlock(); |
1839 | in_dev_put(in_dev); | 1718 | in_dev_put(in_dev); |
1840 | } | 1719 | } |
1841 | } | 1720 | } |
@@ -1848,10 +1727,10 @@ static void qeth_l3_add_multicast_ipv4(struct qeth_card *card) | |||
1848 | in4_dev = in_dev_get(card->dev); | 1727 | in4_dev = in_dev_get(card->dev); |
1849 | if (in4_dev == NULL) | 1728 | if (in4_dev == NULL) |
1850 | return; | 1729 | return; |
1851 | read_lock(&in4_dev->mc_list_lock); | 1730 | rcu_read_lock(); |
1852 | qeth_l3_add_mc(card, in4_dev); | 1731 | qeth_l3_add_mc(card, in4_dev); |
1853 | qeth_l3_add_vlan_mc(card); | 1732 | qeth_l3_add_vlan_mc(card); |
1854 | read_unlock(&in4_dev->mc_list_lock); | 1733 | rcu_read_unlock(); |
1855 | in_dev_put(in4_dev); | 1734 | in_dev_put(in4_dev); |
1856 | } | 1735 | } |
1857 | 1736 | ||
@@ -1888,7 +1767,7 @@ static void qeth_l3_add_vlan_mc6(struct qeth_card *card) | |||
1888 | return; | 1767 | return; |
1889 | 1768 | ||
1890 | vg = card->vlangrp; | 1769 | vg = card->vlangrp; |
1891 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 1770 | for (i = 0; i < VLAN_N_VID; i++) { |
1892 | struct net_device *netdev = vlan_group_get_device(vg, i); | 1771 | struct net_device *netdev = vlan_group_get_device(vg, i); |
1893 | if (netdev == NULL || | 1772 | if (netdev == NULL || |
1894 | !(netdev->flags & IFF_UP)) | 1773 | !(netdev->flags & IFF_UP)) |
@@ -2018,13 +1897,14 @@ static void qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | |||
2018 | qeth_l3_set_multicast_list(card->dev); | 1897 | qeth_l3_set_multicast_list(card->dev); |
2019 | } | 1898 | } |
2020 | 1899 | ||
2021 | static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card, | 1900 | static inline int qeth_l3_rebuild_skb(struct qeth_card *card, |
2022 | struct sk_buff *skb, struct qeth_hdr *hdr) | 1901 | struct sk_buff *skb, struct qeth_hdr *hdr, |
1902 | unsigned short *vlan_id) | ||
2023 | { | 1903 | { |
2024 | unsigned short vlan_id = 0; | ||
2025 | __be16 prot; | 1904 | __be16 prot; |
2026 | struct iphdr *ip_hdr; | 1905 | struct iphdr *ip_hdr; |
2027 | unsigned char tg_addr[MAX_ADDR_LEN]; | 1906 | unsigned char tg_addr[MAX_ADDR_LEN]; |
1907 | int is_vlan = 0; | ||
2028 | 1908 | ||
2029 | if (!(hdr->hdr.l3.flags & QETH_HDR_PASSTHRU)) { | 1909 | if (!(hdr->hdr.l3.flags & QETH_HDR_PASSTHRU)) { |
2030 | prot = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 : | 1910 | prot = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 : |
@@ -2087,18 +1967,12 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card, | |||
2087 | 1967 | ||
2088 | if (hdr->hdr.l3.ext_flags & | 1968 | if (hdr->hdr.l3.ext_flags & |
2089 | (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) { | 1969 | (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) { |
2090 | vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)? | 1970 | *vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME) ? |
2091 | hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]); | 1971 | hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]); |
1972 | is_vlan = 1; | ||
2092 | } | 1973 | } |
2093 | 1974 | ||
2094 | switch (card->options.checksum_type) { | 1975 | if (card->dev->features & NETIF_F_RXCSUM) { |
2095 | case SW_CHECKSUMMING: | ||
2096 | skb->ip_summed = CHECKSUM_NONE; | ||
2097 | break; | ||
2098 | case NO_CHECKSUMMING: | ||
2099 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
2100 | break; | ||
2101 | case HW_CHECKSUMMING: | ||
2102 | if ((hdr->hdr.l3.ext_flags & | 1976 | if ((hdr->hdr.l3.ext_flags & |
2103 | (QETH_HDR_EXT_CSUM_HDR_REQ | | 1977 | (QETH_HDR_EXT_CSUM_HDR_REQ | |
2104 | QETH_HDR_EXT_CSUM_TRANSP_REQ)) == | 1978 | QETH_HDR_EXT_CSUM_TRANSP_REQ)) == |
@@ -2107,56 +1981,47 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card, | |||
2107 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 1981 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
2108 | else | 1982 | else |
2109 | skb->ip_summed = CHECKSUM_NONE; | 1983 | skb->ip_summed = CHECKSUM_NONE; |
2110 | } | 1984 | } else |
1985 | skb->ip_summed = CHECKSUM_NONE; | ||
2111 | 1986 | ||
2112 | return vlan_id; | 1987 | return is_vlan; |
2113 | } | 1988 | } |
2114 | 1989 | ||
2115 | static void qeth_l3_process_inbound_buffer(struct qeth_card *card, | 1990 | static int qeth_l3_process_inbound_buffer(struct qeth_card *card, |
2116 | struct qeth_qdio_buffer *buf, int index) | 1991 | int budget, int *done) |
2117 | { | 1992 | { |
2118 | struct qdio_buffer_element *element; | 1993 | int work_done = 0; |
2119 | struct sk_buff *skb; | 1994 | struct sk_buff *skb; |
2120 | struct qeth_hdr *hdr; | 1995 | struct qeth_hdr *hdr; |
2121 | int offset; | ||
2122 | __u16 vlan_tag = 0; | 1996 | __u16 vlan_tag = 0; |
1997 | int is_vlan; | ||
2123 | unsigned int len; | 1998 | unsigned int len; |
2124 | /* get first element of current buffer */ | ||
2125 | element = (struct qdio_buffer_element *)&buf->buffer->element[0]; | ||
2126 | offset = 0; | ||
2127 | if (card->options.performance_stats) | ||
2128 | card->perf_stats.bufs_rec++; | ||
2129 | while ((skb = qeth_core_get_next_skb(card, buf->buffer, &element, | ||
2130 | &offset, &hdr))) { | ||
2131 | skb->dev = card->dev; | ||
2132 | /* is device UP ? */ | ||
2133 | if (!(card->dev->flags & IFF_UP)) { | ||
2134 | dev_kfree_skb_any(skb); | ||
2135 | continue; | ||
2136 | } | ||
2137 | 1999 | ||
2000 | *done = 0; | ||
2001 | BUG_ON(!budget); | ||
2002 | while (budget) { | ||
2003 | skb = qeth_core_get_next_skb(card, | ||
2004 | card->qdio.in_q->bufs[card->rx.b_index].buffer, | ||
2005 | &card->rx.b_element, &card->rx.e_offset, &hdr); | ||
2006 | if (!skb) { | ||
2007 | *done = 1; | ||
2008 | break; | ||
2009 | } | ||
2010 | skb->dev = card->dev; | ||
2138 | switch (hdr->hdr.l3.id) { | 2011 | switch (hdr->hdr.l3.id) { |
2139 | case QETH_HEADER_TYPE_LAYER3: | 2012 | case QETH_HEADER_TYPE_LAYER3: |
2140 | vlan_tag = qeth_l3_rebuild_skb(card, skb, hdr); | 2013 | is_vlan = qeth_l3_rebuild_skb(card, skb, hdr, |
2014 | &vlan_tag); | ||
2141 | len = skb->len; | 2015 | len = skb->len; |
2142 | if (vlan_tag && !card->options.sniffer) | 2016 | if (is_vlan && !card->options.sniffer) |
2143 | if (card->vlangrp) | 2017 | vlan_gro_receive(&card->napi, card->vlangrp, |
2144 | vlan_hwaccel_rx(skb, card->vlangrp, | 2018 | vlan_tag, skb); |
2145 | vlan_tag); | ||
2146 | else { | ||
2147 | dev_kfree_skb_any(skb); | ||
2148 | continue; | ||
2149 | } | ||
2150 | else | 2019 | else |
2151 | netif_rx(skb); | 2020 | napi_gro_receive(&card->napi, skb); |
2152 | break; | 2021 | break; |
2153 | case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */ | 2022 | case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */ |
2154 | skb->pkt_type = PACKET_HOST; | 2023 | skb->pkt_type = PACKET_HOST; |
2155 | skb->protocol = eth_type_trans(skb, skb->dev); | 2024 | skb->protocol = eth_type_trans(skb, skb->dev); |
2156 | if (card->options.checksum_type == NO_CHECKSUMMING) | ||
2157 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
2158 | else | ||
2159 | skb->ip_summed = CHECKSUM_NONE; | ||
2160 | len = skb->len; | 2025 | len = skb->len; |
2161 | netif_receive_skb(skb); | 2026 | netif_receive_skb(skb); |
2162 | break; | 2027 | break; |
@@ -2166,10 +2031,87 @@ static void qeth_l3_process_inbound_buffer(struct qeth_card *card, | |||
2166 | QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN); | 2031 | QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN); |
2167 | continue; | 2032 | continue; |
2168 | } | 2033 | } |
2169 | 2034 | work_done++; | |
2035 | budget--; | ||
2170 | card->stats.rx_packets++; | 2036 | card->stats.rx_packets++; |
2171 | card->stats.rx_bytes += len; | 2037 | card->stats.rx_bytes += len; |
2172 | } | 2038 | } |
2039 | return work_done; | ||
2040 | } | ||
2041 | |||
2042 | static int qeth_l3_poll(struct napi_struct *napi, int budget) | ||
2043 | { | ||
2044 | struct qeth_card *card = container_of(napi, struct qeth_card, napi); | ||
2045 | int work_done = 0; | ||
2046 | struct qeth_qdio_buffer *buffer; | ||
2047 | int done; | ||
2048 | int new_budget = budget; | ||
2049 | |||
2050 | if (card->options.performance_stats) { | ||
2051 | card->perf_stats.inbound_cnt++; | ||
2052 | card->perf_stats.inbound_start_time = qeth_get_micros(); | ||
2053 | } | ||
2054 | |||
2055 | while (1) { | ||
2056 | if (!card->rx.b_count) { | ||
2057 | card->rx.qdio_err = 0; | ||
2058 | card->rx.b_count = qdio_get_next_buffers( | ||
2059 | card->data.ccwdev, 0, &card->rx.b_index, | ||
2060 | &card->rx.qdio_err); | ||
2061 | if (card->rx.b_count <= 0) { | ||
2062 | card->rx.b_count = 0; | ||
2063 | break; | ||
2064 | } | ||
2065 | card->rx.b_element = | ||
2066 | &card->qdio.in_q->bufs[card->rx.b_index] | ||
2067 | .buffer->element[0]; | ||
2068 | card->rx.e_offset = 0; | ||
2069 | } | ||
2070 | |||
2071 | while (card->rx.b_count) { | ||
2072 | buffer = &card->qdio.in_q->bufs[card->rx.b_index]; | ||
2073 | if (!(card->rx.qdio_err && | ||
2074 | qeth_check_qdio_errors(card, buffer->buffer, | ||
2075 | card->rx.qdio_err, "qinerr"))) | ||
2076 | work_done += qeth_l3_process_inbound_buffer( | ||
2077 | card, new_budget, &done); | ||
2078 | else | ||
2079 | done = 1; | ||
2080 | |||
2081 | if (done) { | ||
2082 | if (card->options.performance_stats) | ||
2083 | card->perf_stats.bufs_rec++; | ||
2084 | qeth_put_buffer_pool_entry(card, | ||
2085 | buffer->pool_entry); | ||
2086 | qeth_queue_input_buffer(card, card->rx.b_index); | ||
2087 | card->rx.b_count--; | ||
2088 | if (card->rx.b_count) { | ||
2089 | card->rx.b_index = | ||
2090 | (card->rx.b_index + 1) % | ||
2091 | QDIO_MAX_BUFFERS_PER_Q; | ||
2092 | card->rx.b_element = | ||
2093 | &card->qdio.in_q | ||
2094 | ->bufs[card->rx.b_index] | ||
2095 | .buffer->element[0]; | ||
2096 | card->rx.e_offset = 0; | ||
2097 | } | ||
2098 | } | ||
2099 | |||
2100 | if (work_done >= budget) | ||
2101 | goto out; | ||
2102 | else | ||
2103 | new_budget = budget - work_done; | ||
2104 | } | ||
2105 | } | ||
2106 | |||
2107 | napi_complete(napi); | ||
2108 | if (qdio_start_irq(card->data.ccwdev, 0)) | ||
2109 | napi_schedule(&card->napi); | ||
2110 | out: | ||
2111 | if (card->options.performance_stats) | ||
2112 | card->perf_stats.inbound_time += qeth_get_micros() - | ||
2113 | card->perf_stats.inbound_start_time; | ||
2114 | return work_done; | ||
2173 | } | 2115 | } |
2174 | 2116 | ||
2175 | static int qeth_l3_verify_vlan_dev(struct net_device *dev, | 2117 | static int qeth_l3_verify_vlan_dev(struct net_device *dev, |
@@ -2183,7 +2125,7 @@ static int qeth_l3_verify_vlan_dev(struct net_device *dev, | |||
2183 | if (!vg) | 2125 | if (!vg) |
2184 | return rc; | 2126 | return rc; |
2185 | 2127 | ||
2186 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 2128 | for (i = 0; i < VLAN_N_VID; i++) { |
2187 | if (vlan_group_get_device(vg, i) == dev) { | 2129 | if (vlan_group_get_device(vg, i) == dev) { |
2188 | rc = QETH_VLAN_CARD; | 2130 | rc = QETH_VLAN_CARD; |
2189 | break; | 2131 | break; |
@@ -2255,25 +2197,14 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode) | |||
2255 | dev_close(card->dev); | 2197 | dev_close(card->dev); |
2256 | rtnl_unlock(); | 2198 | rtnl_unlock(); |
2257 | } | 2199 | } |
2258 | if (!card->use_hard_stop) { | ||
2259 | rc = qeth_send_stoplan(card); | ||
2260 | if (rc) | ||
2261 | QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); | ||
2262 | } | ||
2263 | card->state = CARD_STATE_SOFTSETUP; | 2200 | card->state = CARD_STATE_SOFTSETUP; |
2264 | } | 2201 | } |
2265 | if (card->state == CARD_STATE_SOFTSETUP) { | 2202 | if (card->state == CARD_STATE_SOFTSETUP) { |
2266 | qeth_l3_clear_ip_list(card, !card->use_hard_stop, 1); | 2203 | qeth_l3_clear_ip_list(card, 1); |
2267 | qeth_clear_ipacmd_list(card); | 2204 | qeth_clear_ipacmd_list(card); |
2268 | card->state = CARD_STATE_HARDSETUP; | 2205 | card->state = CARD_STATE_HARDSETUP; |
2269 | } | 2206 | } |
2270 | if (card->state == CARD_STATE_HARDSETUP) { | 2207 | if (card->state == CARD_STATE_HARDSETUP) { |
2271 | if (!card->use_hard_stop && | ||
2272 | (card->info.type != QETH_CARD_TYPE_IQD)) { | ||
2273 | rc = qeth_l3_put_unique_id(card); | ||
2274 | if (rc) | ||
2275 | QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc); | ||
2276 | } | ||
2277 | qeth_qdio_clear_card(card, 0); | 2208 | qeth_qdio_clear_card(card, 0); |
2278 | qeth_clear_qdio_buffers(card); | 2209 | qeth_clear_qdio_buffers(card); |
2279 | qeth_clear_working_pool_list(card); | 2210 | qeth_clear_working_pool_list(card); |
@@ -2283,7 +2214,6 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode) | |||
2283 | qeth_clear_cmd_buffers(&card->read); | 2214 | qeth_clear_cmd_buffers(&card->read); |
2284 | qeth_clear_cmd_buffers(&card->write); | 2215 | qeth_clear_cmd_buffers(&card->write); |
2285 | } | 2216 | } |
2286 | card->use_hard_stop = 0; | ||
2287 | return rc; | 2217 | return rc; |
2288 | } | 2218 | } |
2289 | 2219 | ||
@@ -2390,22 +2320,46 @@ static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries) | |||
2390 | return rc; | 2320 | return rc; |
2391 | } | 2321 | } |
2392 | 2322 | ||
2393 | static void qeth_l3_copy_arp_entries_stripped(struct qeth_arp_query_info *qinfo, | 2323 | static __u32 get_arp_entry_size(struct qeth_card *card, |
2394 | struct qeth_arp_query_data *qdata, int entry_size, | 2324 | struct qeth_arp_query_data *qdata, |
2395 | int uentry_size) | 2325 | struct qeth_arp_entrytype *type, __u8 strip_entries) |
2396 | { | 2326 | { |
2397 | char *entry_ptr; | 2327 | __u32 rc; |
2398 | char *uentry_ptr; | 2328 | __u8 is_hsi; |
2399 | int i; | ||
2400 | 2329 | ||
2401 | entry_ptr = (char *)&qdata->data; | 2330 | is_hsi = qdata->reply_bits == 5; |
2402 | uentry_ptr = (char *)(qinfo->udata + qinfo->udata_offset); | 2331 | if (type->ip == QETHARP_IP_ADDR_V4) { |
2403 | for (i = 0; i < qdata->no_entries; ++i) { | 2332 | QETH_CARD_TEXT(card, 4, "arpev4"); |
2404 | /* strip off 32 bytes "media specific information" */ | 2333 | if (strip_entries) { |
2405 | memcpy(uentry_ptr, (entry_ptr + 32), entry_size - 32); | 2334 | rc = is_hsi ? sizeof(struct qeth_arp_qi_entry5_short) : |
2406 | entry_ptr += entry_size; | 2335 | sizeof(struct qeth_arp_qi_entry7_short); |
2407 | uentry_ptr += uentry_size; | 2336 | } else { |
2337 | rc = is_hsi ? sizeof(struct qeth_arp_qi_entry5) : | ||
2338 | sizeof(struct qeth_arp_qi_entry7); | ||
2339 | } | ||
2340 | } else if (type->ip == QETHARP_IP_ADDR_V6) { | ||
2341 | QETH_CARD_TEXT(card, 4, "arpev6"); | ||
2342 | if (strip_entries) { | ||
2343 | rc = is_hsi ? | ||
2344 | sizeof(struct qeth_arp_qi_entry5_short_ipv6) : | ||
2345 | sizeof(struct qeth_arp_qi_entry7_short_ipv6); | ||
2346 | } else { | ||
2347 | rc = is_hsi ? | ||
2348 | sizeof(struct qeth_arp_qi_entry5_ipv6) : | ||
2349 | sizeof(struct qeth_arp_qi_entry7_ipv6); | ||
2350 | } | ||
2351 | } else { | ||
2352 | QETH_CARD_TEXT(card, 4, "arpinv"); | ||
2353 | rc = 0; | ||
2408 | } | 2354 | } |
2355 | |||
2356 | return rc; | ||
2357 | } | ||
2358 | |||
2359 | static int arpentry_matches_prot(struct qeth_arp_entrytype *type, __u16 prot) | ||
2360 | { | ||
2361 | return (type->ip == QETHARP_IP_ADDR_V4 && prot == QETH_PROT_IPV4) || | ||
2362 | (type->ip == QETHARP_IP_ADDR_V6 && prot == QETH_PROT_IPV6); | ||
2409 | } | 2363 | } |
2410 | 2364 | ||
2411 | static int qeth_l3_arp_query_cb(struct qeth_card *card, | 2365 | static int qeth_l3_arp_query_cb(struct qeth_card *card, |
@@ -2414,72 +2368,77 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card, | |||
2414 | struct qeth_ipa_cmd *cmd; | 2368 | struct qeth_ipa_cmd *cmd; |
2415 | struct qeth_arp_query_data *qdata; | 2369 | struct qeth_arp_query_data *qdata; |
2416 | struct qeth_arp_query_info *qinfo; | 2370 | struct qeth_arp_query_info *qinfo; |
2417 | int entry_size; | ||
2418 | int uentry_size; | ||
2419 | int i; | 2371 | int i; |
2372 | int e; | ||
2373 | int entrybytes_done; | ||
2374 | int stripped_bytes; | ||
2375 | __u8 do_strip_entries; | ||
2420 | 2376 | ||
2421 | QETH_CARD_TEXT(card, 4, "arpquecb"); | 2377 | QETH_CARD_TEXT(card, 3, "arpquecb"); |
2422 | 2378 | ||
2423 | qinfo = (struct qeth_arp_query_info *) reply->param; | 2379 | qinfo = (struct qeth_arp_query_info *) reply->param; |
2424 | cmd = (struct qeth_ipa_cmd *) data; | 2380 | cmd = (struct qeth_ipa_cmd *) data; |
2381 | QETH_CARD_TEXT_(card, 4, "%i", cmd->hdr.prot_version); | ||
2425 | if (cmd->hdr.return_code) { | 2382 | if (cmd->hdr.return_code) { |
2426 | QETH_CARD_TEXT_(card, 4, "qaer1%i", cmd->hdr.return_code); | 2383 | QETH_CARD_TEXT(card, 4, "arpcberr"); |
2384 | QETH_CARD_TEXT_(card, 4, "%i", cmd->hdr.return_code); | ||
2427 | return 0; | 2385 | return 0; |
2428 | } | 2386 | } |
2429 | if (cmd->data.setassparms.hdr.return_code) { | 2387 | if (cmd->data.setassparms.hdr.return_code) { |
2430 | cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code; | 2388 | cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code; |
2431 | QETH_CARD_TEXT_(card, 4, "qaer2%i", cmd->hdr.return_code); | 2389 | QETH_CARD_TEXT(card, 4, "setaperr"); |
2390 | QETH_CARD_TEXT_(card, 4, "%i", cmd->hdr.return_code); | ||
2432 | return 0; | 2391 | return 0; |
2433 | } | 2392 | } |
2434 | qdata = &cmd->data.setassparms.data.query_arp; | 2393 | qdata = &cmd->data.setassparms.data.query_arp; |
2435 | switch (qdata->reply_bits) { | ||
2436 | case 5: | ||
2437 | uentry_size = entry_size = sizeof(struct qeth_arp_qi_entry5); | ||
2438 | if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) | ||
2439 | uentry_size = sizeof(struct qeth_arp_qi_entry5_short); | ||
2440 | break; | ||
2441 | case 7: | ||
2442 | /* fall through to default */ | ||
2443 | default: | ||
2444 | /* tr is the same as eth -> entry7 */ | ||
2445 | uentry_size = entry_size = sizeof(struct qeth_arp_qi_entry7); | ||
2446 | if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) | ||
2447 | uentry_size = sizeof(struct qeth_arp_qi_entry7_short); | ||
2448 | break; | ||
2449 | } | ||
2450 | /* check if there is enough room in userspace */ | ||
2451 | if ((qinfo->udata_len - qinfo->udata_offset) < | ||
2452 | qdata->no_entries * uentry_size){ | ||
2453 | QETH_CARD_TEXT_(card, 4, "qaer3%i", -ENOMEM); | ||
2454 | cmd->hdr.return_code = -ENOMEM; | ||
2455 | goto out_error; | ||
2456 | } | ||
2457 | QETH_CARD_TEXT_(card, 4, "anore%i", | ||
2458 | cmd->data.setassparms.hdr.number_of_replies); | ||
2459 | QETH_CARD_TEXT_(card, 4, "aseqn%i", cmd->data.setassparms.hdr.seq_no); | ||
2460 | QETH_CARD_TEXT_(card, 4, "anoen%i", qdata->no_entries); | 2394 | QETH_CARD_TEXT_(card, 4, "anoen%i", qdata->no_entries); |
2461 | 2395 | ||
2462 | if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) { | 2396 | do_strip_entries = (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) > 0; |
2463 | /* strip off "media specific information" */ | 2397 | stripped_bytes = do_strip_entries ? QETH_QARP_MEDIASPECIFIC_BYTES : 0; |
2464 | qeth_l3_copy_arp_entries_stripped(qinfo, qdata, entry_size, | 2398 | entrybytes_done = 0; |
2465 | uentry_size); | 2399 | for (e = 0; e < qdata->no_entries; ++e) { |
2466 | } else | 2400 | char *cur_entry; |
2467 | /*copy entries to user buffer*/ | 2401 | __u32 esize; |
2468 | memcpy(qinfo->udata + qinfo->udata_offset, | 2402 | struct qeth_arp_entrytype *etype; |
2469 | (char *)&qdata->data, qdata->no_entries*uentry_size); | 2403 | |
2404 | cur_entry = &qdata->data + entrybytes_done; | ||
2405 | etype = &((struct qeth_arp_qi_entry5 *) cur_entry)->type; | ||
2406 | if (!arpentry_matches_prot(etype, cmd->hdr.prot_version)) { | ||
2407 | QETH_CARD_TEXT(card, 4, "pmis"); | ||
2408 | QETH_CARD_TEXT_(card, 4, "%i", etype->ip); | ||
2409 | break; | ||
2410 | } | ||
2411 | esize = get_arp_entry_size(card, qdata, etype, | ||
2412 | do_strip_entries); | ||
2413 | QETH_CARD_TEXT_(card, 5, "esz%i", esize); | ||
2414 | if (!esize) | ||
2415 | break; | ||
2416 | |||
2417 | if ((qinfo->udata_len - qinfo->udata_offset) < esize) { | ||
2418 | QETH_CARD_TEXT_(card, 4, "qaer3%i", -ENOMEM); | ||
2419 | cmd->hdr.return_code = -ENOMEM; | ||
2420 | goto out_error; | ||
2421 | } | ||
2470 | 2422 | ||
2471 | qinfo->no_entries += qdata->no_entries; | 2423 | memcpy(qinfo->udata + qinfo->udata_offset, |
2472 | qinfo->udata_offset += (qdata->no_entries*uentry_size); | 2424 | &qdata->data + entrybytes_done + stripped_bytes, |
2425 | esize); | ||
2426 | entrybytes_done += esize + stripped_bytes; | ||
2427 | qinfo->udata_offset += esize; | ||
2428 | ++qinfo->no_entries; | ||
2429 | } | ||
2473 | /* check if all replies received ... */ | 2430 | /* check if all replies received ... */ |
2474 | if (cmd->data.setassparms.hdr.seq_no < | 2431 | if (cmd->data.setassparms.hdr.seq_no < |
2475 | cmd->data.setassparms.hdr.number_of_replies) | 2432 | cmd->data.setassparms.hdr.number_of_replies) |
2476 | return 1; | 2433 | return 1; |
2434 | QETH_CARD_TEXT_(card, 4, "nove%i", qinfo->no_entries); | ||
2477 | memcpy(qinfo->udata, &qinfo->no_entries, 4); | 2435 | memcpy(qinfo->udata, &qinfo->no_entries, 4); |
2478 | /* keep STRIP_ENTRIES flag so the user program can distinguish | 2436 | /* keep STRIP_ENTRIES flag so the user program can distinguish |
2479 | * stripped entries from normal ones */ | 2437 | * stripped entries from normal ones */ |
2480 | if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) | 2438 | if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) |
2481 | qdata->reply_bits |= QETH_QARP_STRIP_ENTRIES; | 2439 | qdata->reply_bits |= QETH_QARP_STRIP_ENTRIES; |
2482 | memcpy(qinfo->udata + QETH_QARP_MASK_OFFSET, &qdata->reply_bits, 2); | 2440 | memcpy(qinfo->udata + QETH_QARP_MASK_OFFSET, &qdata->reply_bits, 2); |
2441 | QETH_CARD_TEXT_(card, 4, "rc%i", 0); | ||
2483 | return 0; | 2442 | return 0; |
2484 | out_error: | 2443 | out_error: |
2485 | i = 0; | 2444 | i = 0; |
@@ -2502,45 +2461,86 @@ static int qeth_l3_send_ipa_arp_cmd(struct qeth_card *card, | |||
2502 | reply_cb, reply_param); | 2461 | reply_cb, reply_param); |
2503 | } | 2462 | } |
2504 | 2463 | ||
2505 | static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata) | 2464 | static int qeth_l3_query_arp_cache_info(struct qeth_card *card, |
2465 | enum qeth_prot_versions prot, | ||
2466 | struct qeth_arp_query_info *qinfo) | ||
2506 | { | 2467 | { |
2507 | struct qeth_cmd_buffer *iob; | 2468 | struct qeth_cmd_buffer *iob; |
2508 | struct qeth_arp_query_info qinfo = {0, }; | 2469 | struct qeth_ipa_cmd *cmd; |
2509 | int tmp; | 2470 | int tmp; |
2510 | int rc; | 2471 | int rc; |
2511 | 2472 | ||
2473 | QETH_CARD_TEXT_(card, 3, "qarpipv%i", prot); | ||
2474 | |||
2475 | iob = qeth_l3_get_setassparms_cmd(card, IPA_ARP_PROCESSING, | ||
2476 | IPA_CMD_ASS_ARP_QUERY_INFO, | ||
2477 | sizeof(struct qeth_arp_query_data) - sizeof(char), | ||
2478 | prot); | ||
2479 | cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); | ||
2480 | cmd->data.setassparms.data.query_arp.request_bits = 0x000F; | ||
2481 | cmd->data.setassparms.data.query_arp.reply_bits = 0; | ||
2482 | cmd->data.setassparms.data.query_arp.no_entries = 0; | ||
2483 | rc = qeth_l3_send_ipa_arp_cmd(card, iob, | ||
2484 | QETH_SETASS_BASE_LEN+QETH_ARP_CMD_LEN, | ||
2485 | qeth_l3_arp_query_cb, (void *)qinfo); | ||
2486 | if (rc) { | ||
2487 | tmp = rc; | ||
2488 | QETH_DBF_MESSAGE(2, | ||
2489 | "Error while querying ARP cache on %s: %s " | ||
2490 | "(0x%x/%d)\n", QETH_CARD_IFNAME(card), | ||
2491 | qeth_l3_arp_get_error_cause(&rc), tmp, tmp); | ||
2492 | } | ||
2493 | |||
2494 | return rc; | ||
2495 | } | ||
2496 | |||
2497 | static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata) | ||
2498 | { | ||
2499 | struct qeth_arp_query_info qinfo = {0, }; | ||
2500 | int rc; | ||
2501 | |||
2512 | QETH_CARD_TEXT(card, 3, "arpquery"); | 2502 | QETH_CARD_TEXT(card, 3, "arpquery"); |
2513 | 2503 | ||
2514 | if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/ | 2504 | if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/ |
2515 | IPA_ARP_PROCESSING)) { | 2505 | IPA_ARP_PROCESSING)) { |
2516 | return -EOPNOTSUPP; | 2506 | QETH_CARD_TEXT(card, 3, "arpqnsup"); |
2507 | rc = -EOPNOTSUPP; | ||
2508 | goto out; | ||
2517 | } | 2509 | } |
2518 | /* get size of userspace buffer and mask_bits -> 6 bytes */ | 2510 | /* get size of userspace buffer and mask_bits -> 6 bytes */ |
2519 | if (copy_from_user(&qinfo, udata, 6)) | 2511 | if (copy_from_user(&qinfo, udata, 6)) { |
2520 | return -EFAULT; | 2512 | rc = -EFAULT; |
2513 | goto out; | ||
2514 | } | ||
2521 | qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL); | 2515 | qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL); |
2522 | if (!qinfo.udata) | 2516 | if (!qinfo.udata) { |
2523 | return -ENOMEM; | 2517 | rc = -ENOMEM; |
2518 | goto out; | ||
2519 | } | ||
2524 | qinfo.udata_offset = QETH_QARP_ENTRIES_OFFSET; | 2520 | qinfo.udata_offset = QETH_QARP_ENTRIES_OFFSET; |
2525 | iob = qeth_l3_get_setassparms_cmd(card, IPA_ARP_PROCESSING, | 2521 | rc = qeth_l3_query_arp_cache_info(card, QETH_PROT_IPV4, &qinfo); |
2526 | IPA_CMD_ASS_ARP_QUERY_INFO, | ||
2527 | sizeof(int), QETH_PROT_IPV4); | ||
2528 | |||
2529 | rc = qeth_l3_send_ipa_arp_cmd(card, iob, | ||
2530 | QETH_SETASS_BASE_LEN+QETH_ARP_CMD_LEN, | ||
2531 | qeth_l3_arp_query_cb, (void *)&qinfo); | ||
2532 | if (rc) { | 2522 | if (rc) { |
2533 | tmp = rc; | ||
2534 | QETH_DBF_MESSAGE(2, "Error while querying ARP cache on %s: %s " | ||
2535 | "(0x%x/%d)\n", QETH_CARD_IFNAME(card), | ||
2536 | qeth_l3_arp_get_error_cause(&rc), tmp, tmp); | ||
2537 | if (copy_to_user(udata, qinfo.udata, 4)) | 2523 | if (copy_to_user(udata, qinfo.udata, 4)) |
2538 | rc = -EFAULT; | 2524 | rc = -EFAULT; |
2525 | goto free_and_out; | ||
2539 | } else { | 2526 | } else { |
2540 | if (copy_to_user(udata, qinfo.udata, qinfo.udata_len)) | 2527 | #ifdef CONFIG_QETH_IPV6 |
2528 | if (qinfo.mask_bits & QETH_QARP_WITH_IPV6) { | ||
2529 | /* fails in case of GuestLAN QDIO mode */ | ||
2530 | qeth_l3_query_arp_cache_info(card, QETH_PROT_IPV6, | ||
2531 | &qinfo); | ||
2532 | } | ||
2533 | #endif | ||
2534 | if (copy_to_user(udata, qinfo.udata, qinfo.udata_len)) { | ||
2535 | QETH_CARD_TEXT(card, 4, "qactf"); | ||
2541 | rc = -EFAULT; | 2536 | rc = -EFAULT; |
2537 | goto free_and_out; | ||
2538 | } | ||
2539 | QETH_CARD_TEXT_(card, 4, "qacts"); | ||
2542 | } | 2540 | } |
2541 | free_and_out: | ||
2543 | kfree(qinfo.udata); | 2542 | kfree(qinfo.udata); |
2543 | out: | ||
2544 | return rc; | 2544 | return rc; |
2545 | } | 2545 | } |
2546 | 2546 | ||
@@ -2859,7 +2859,9 @@ static inline void qeth_l3_hdr_csum(struct qeth_card *card, | |||
2859 | */ | 2859 | */ |
2860 | if (iph->protocol == IPPROTO_UDP) | 2860 | if (iph->protocol == IPPROTO_UDP) |
2861 | hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_UDP; | 2861 | hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_UDP; |
2862 | hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_CSUM_TRANSP_REQ; | 2862 | hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_CSUM_TRANSP_REQ | |
2863 | QETH_HDR_EXT_CSUM_HDR_REQ; | ||
2864 | iph->check = 0; | ||
2863 | if (card->options.performance_stats) | 2865 | if (card->options.performance_stats) |
2864 | card->perf_stats.tx_csum++; | 2866 | card->perf_stats.tx_csum++; |
2865 | } | 2867 | } |
@@ -2874,6 +2876,7 @@ static void qeth_tso_fill_header(struct qeth_card *card, | |||
2874 | 2876 | ||
2875 | /*fix header to TSO values ...*/ | 2877 | /*fix header to TSO values ...*/ |
2876 | hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO; | 2878 | hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO; |
2879 | hdr->hdr.hdr.l3.length = skb->len - sizeof(struct qeth_hdr_tso); | ||
2877 | /*set values which are fix for the first approach ...*/ | 2880 | /*set values which are fix for the first approach ...*/ |
2878 | hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso); | 2881 | hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso); |
2879 | hdr->ext.imb_hdr_no = 1; | 2882 | hdr->ext.imb_hdr_no = 1; |
@@ -2923,7 +2926,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2923 | struct qeth_qdio_out_q *queue = card->qdio.out_qs | 2926 | struct qeth_qdio_out_q *queue = card->qdio.out_qs |
2924 | [qeth_get_priority_queue(card, skb, ipv, cast_type)]; | 2927 | [qeth_get_priority_queue(card, skb, ipv, cast_type)]; |
2925 | int tx_bytes = skb->len; | 2928 | int tx_bytes = skb->len; |
2926 | enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; | 2929 | bool large_send; |
2927 | int data_offset = -1; | 2930 | int data_offset = -1; |
2928 | int nr_frags; | 2931 | int nr_frags; |
2929 | 2932 | ||
@@ -2945,8 +2948,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2945 | card->perf_stats.outbound_start_time = qeth_get_micros(); | 2948 | card->perf_stats.outbound_start_time = qeth_get_micros(); |
2946 | } | 2949 | } |
2947 | 2950 | ||
2948 | if (skb_is_gso(skb)) | 2951 | large_send = skb_is_gso(skb); |
2949 | large_send = card->options.large_send; | ||
2950 | 2952 | ||
2951 | if ((card->info.type == QETH_CARD_TYPE_IQD) && (!large_send) && | 2953 | if ((card->info.type == QETH_CARD_TYPE_IQD) && (!large_send) && |
2952 | (skb_shinfo(skb)->nr_frags == 0)) { | 2954 | (skb_shinfo(skb)->nr_frags == 0)) { |
@@ -2975,7 +2977,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2975 | skb_pull(new_skb, ETH_HLEN); | 2977 | skb_pull(new_skb, ETH_HLEN); |
2976 | } | 2978 | } |
2977 | 2979 | ||
2978 | if (ipv == 6 && card->vlangrp && | 2980 | if (ipv != 4 && card->vlangrp && |
2979 | vlan_tx_tag_present(new_skb)) { | 2981 | vlan_tx_tag_present(new_skb)) { |
2980 | skb_push(new_skb, VLAN_HLEN); | 2982 | skb_push(new_skb, VLAN_HLEN); |
2981 | skb_copy_to_linear_data(new_skb, new_skb->data + 4, 4); | 2983 | skb_copy_to_linear_data(new_skb, new_skb->data + 4, 4); |
@@ -2995,7 +2997,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2995 | /* fix hardware limitation: as long as we do not have sbal | 2997 | /* fix hardware limitation: as long as we do not have sbal |
2996 | * chaining we can not send long frag lists | 2998 | * chaining we can not send long frag lists |
2997 | */ | 2999 | */ |
2998 | if (large_send == QETH_LARGE_SEND_TSO) { | 3000 | if (large_send) { |
2999 | if (qeth_l3_tso_elements(new_skb) + 1 > 16) { | 3001 | if (qeth_l3_tso_elements(new_skb) + 1 > 16) { |
3000 | if (skb_linearize(new_skb)) | 3002 | if (skb_linearize(new_skb)) |
3001 | goto tx_drop; | 3003 | goto tx_drop; |
@@ -3004,8 +3006,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3004 | } | 3006 | } |
3005 | } | 3007 | } |
3006 | 3008 | ||
3007 | if ((large_send == QETH_LARGE_SEND_TSO) && | 3009 | if (large_send && (cast_type == RTN_UNSPEC)) { |
3008 | (cast_type == RTN_UNSPEC)) { | ||
3009 | hdr = (struct qeth_hdr *)skb_push(new_skb, | 3010 | hdr = (struct qeth_hdr *)skb_push(new_skb, |
3010 | sizeof(struct qeth_hdr_tso)); | 3011 | sizeof(struct qeth_hdr_tso)); |
3011 | memset(hdr, 0, sizeof(struct qeth_hdr_tso)); | 3012 | memset(hdr, 0, sizeof(struct qeth_hdr_tso)); |
@@ -3040,7 +3041,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3040 | 3041 | ||
3041 | if (card->info.type != QETH_CARD_TYPE_IQD) { | 3042 | if (card->info.type != QETH_CARD_TYPE_IQD) { |
3042 | int len; | 3043 | int len; |
3043 | if (large_send == QETH_LARGE_SEND_TSO) | 3044 | if (large_send) |
3044 | len = ((unsigned long)tcp_hdr(new_skb) + | 3045 | len = ((unsigned long)tcp_hdr(new_skb) + |
3045 | tcp_hdr(new_skb)->doff * 4) - | 3046 | tcp_hdr(new_skb)->doff * 4) - |
3046 | (unsigned long)new_skb->data; | 3047 | (unsigned long)new_skb->data; |
@@ -3061,7 +3062,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3061 | if (new_skb != skb) | 3062 | if (new_skb != skb) |
3062 | dev_kfree_skb_any(skb); | 3063 | dev_kfree_skb_any(skb); |
3063 | if (card->options.performance_stats) { | 3064 | if (card->options.performance_stats) { |
3064 | if (large_send != QETH_LARGE_SEND_NO) { | 3065 | if (large_send) { |
3065 | card->perf_stats.large_send_bytes += tx_bytes; | 3066 | card->perf_stats.large_send_bytes += tx_bytes; |
3066 | card->perf_stats.large_send_cnt++; | 3067 | card->perf_stats.large_send_cnt++; |
3067 | } | 3068 | } |
@@ -3100,92 +3101,89 @@ tx_drop: | |||
3100 | return NETDEV_TX_OK; | 3101 | return NETDEV_TX_OK; |
3101 | } | 3102 | } |
3102 | 3103 | ||
3103 | static int qeth_l3_open(struct net_device *dev) | 3104 | static int __qeth_l3_open(struct net_device *dev) |
3104 | { | 3105 | { |
3105 | struct qeth_card *card = dev->ml_priv; | 3106 | struct qeth_card *card = dev->ml_priv; |
3107 | int rc = 0; | ||
3106 | 3108 | ||
3107 | QETH_CARD_TEXT(card, 4, "qethopen"); | 3109 | QETH_CARD_TEXT(card, 4, "qethopen"); |
3110 | if (card->state == CARD_STATE_UP) | ||
3111 | return rc; | ||
3108 | if (card->state != CARD_STATE_SOFTSETUP) | 3112 | if (card->state != CARD_STATE_SOFTSETUP) |
3109 | return -ENODEV; | 3113 | return -ENODEV; |
3110 | card->data.state = CH_STATE_UP; | 3114 | card->data.state = CH_STATE_UP; |
3111 | card->state = CARD_STATE_UP; | 3115 | card->state = CARD_STATE_UP; |
3112 | netif_start_queue(dev); | 3116 | netif_start_queue(dev); |
3113 | 3117 | ||
3114 | if (!card->lan_online && netif_carrier_ok(dev)) | 3118 | if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) { |
3115 | netif_carrier_off(dev); | 3119 | napi_enable(&card->napi); |
3116 | return 0; | 3120 | napi_schedule(&card->napi); |
3121 | } else | ||
3122 | rc = -EIO; | ||
3123 | return rc; | ||
3117 | } | 3124 | } |
3118 | 3125 | ||
3119 | static int qeth_l3_stop(struct net_device *dev) | 3126 | static int qeth_l3_open(struct net_device *dev) |
3120 | { | 3127 | { |
3121 | struct qeth_card *card = dev->ml_priv; | 3128 | struct qeth_card *card = dev->ml_priv; |
3122 | 3129 | ||
3123 | QETH_CARD_TEXT(card, 4, "qethstop"); | 3130 | QETH_CARD_TEXT(card, 5, "qethope_"); |
3124 | netif_tx_disable(dev); | 3131 | if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { |
3125 | if (card->state == CARD_STATE_UP) | 3132 | QETH_CARD_TEXT(card, 3, "openREC"); |
3126 | card->state = CARD_STATE_SOFTSETUP; | 3133 | return -ERESTARTSYS; |
3127 | return 0; | 3134 | } |
3135 | return __qeth_l3_open(dev); | ||
3128 | } | 3136 | } |
3129 | 3137 | ||
3130 | static u32 qeth_l3_ethtool_get_rx_csum(struct net_device *dev) | 3138 | static int qeth_l3_stop(struct net_device *dev) |
3131 | { | 3139 | { |
3132 | struct qeth_card *card = dev->ml_priv; | 3140 | struct qeth_card *card = dev->ml_priv; |
3133 | 3141 | ||
3134 | return (card->options.checksum_type == HW_CHECKSUMMING); | 3142 | QETH_CARD_TEXT(card, 4, "qethstop"); |
3143 | netif_tx_disable(dev); | ||
3144 | if (card->state == CARD_STATE_UP) { | ||
3145 | card->state = CARD_STATE_SOFTSETUP; | ||
3146 | napi_disable(&card->napi); | ||
3147 | } | ||
3148 | return 0; | ||
3135 | } | 3149 | } |
3136 | 3150 | ||
3137 | static int qeth_l3_ethtool_set_rx_csum(struct net_device *dev, u32 data) | 3151 | static u32 qeth_l3_fix_features(struct net_device *dev, u32 features) |
3138 | { | 3152 | { |
3139 | struct qeth_card *card = dev->ml_priv; | 3153 | struct qeth_card *card = dev->ml_priv; |
3140 | enum qeth_checksum_types csum_type; | ||
3141 | 3154 | ||
3142 | if (data) | 3155 | if (!qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM)) |
3143 | csum_type = HW_CHECKSUMMING; | 3156 | features &= ~NETIF_F_IP_CSUM; |
3144 | else | 3157 | if (!qeth_is_supported(card, IPA_OUTBOUND_TSO)) |
3145 | csum_type = SW_CHECKSUMMING; | 3158 | features &= ~NETIF_F_TSO; |
3159 | if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) | ||
3160 | features &= ~NETIF_F_RXCSUM; | ||
3146 | 3161 | ||
3147 | return qeth_l3_set_rx_csum(card, csum_type); | 3162 | return features; |
3148 | } | 3163 | } |
3149 | 3164 | ||
3150 | static int qeth_l3_ethtool_set_tso(struct net_device *dev, u32 data) | 3165 | static int qeth_l3_set_features(struct net_device *dev, u32 features) |
3151 | { | 3166 | { |
3152 | struct qeth_card *card = dev->ml_priv; | 3167 | struct qeth_card *card = dev->ml_priv; |
3153 | int rc = 0; | 3168 | u32 changed = dev->features ^ features; |
3169 | int err; | ||
3154 | 3170 | ||
3155 | if (data) { | 3171 | if (!(changed & NETIF_F_RXCSUM)) |
3156 | rc = qeth_l3_set_large_send(card, QETH_LARGE_SEND_TSO); | 3172 | return 0; |
3157 | } else { | ||
3158 | dev->features &= ~NETIF_F_TSO; | ||
3159 | card->options.large_send = QETH_LARGE_SEND_NO; | ||
3160 | } | ||
3161 | return rc; | ||
3162 | } | ||
3163 | 3173 | ||
3164 | static int qeth_l3_ethtool_set_tx_csum(struct net_device *dev, u32 data) | 3174 | if (card->state == CARD_STATE_DOWN || |
3165 | { | 3175 | card->state == CARD_STATE_RECOVER) |
3166 | struct qeth_card *card = dev->ml_priv; | 3176 | return 0; |
3167 | 3177 | ||
3168 | if (data) { | 3178 | err = qeth_l3_set_rx_csum(card, features & NETIF_F_RXCSUM); |
3169 | if (qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM)) | 3179 | if (err) |
3170 | dev->features |= NETIF_F_IP_CSUM; | 3180 | dev->features = features ^ NETIF_F_RXCSUM; |
3171 | else | ||
3172 | return -EPERM; | ||
3173 | } else | ||
3174 | dev->features &= ~NETIF_F_IP_CSUM; | ||
3175 | 3181 | ||
3176 | return 0; | 3182 | return err; |
3177 | } | 3183 | } |
3178 | 3184 | ||
3179 | static const struct ethtool_ops qeth_l3_ethtool_ops = { | 3185 | static const struct ethtool_ops qeth_l3_ethtool_ops = { |
3180 | .get_link = ethtool_op_get_link, | 3186 | .get_link = ethtool_op_get_link, |
3181 | .get_tx_csum = ethtool_op_get_tx_csum, | ||
3182 | .set_tx_csum = qeth_l3_ethtool_set_tx_csum, | ||
3183 | .get_rx_csum = qeth_l3_ethtool_get_rx_csum, | ||
3184 | .set_rx_csum = qeth_l3_ethtool_set_rx_csum, | ||
3185 | .get_sg = ethtool_op_get_sg, | ||
3186 | .set_sg = ethtool_op_set_sg, | ||
3187 | .get_tso = ethtool_op_get_tso, | ||
3188 | .set_tso = qeth_l3_ethtool_set_tso, | ||
3189 | .get_strings = qeth_core_get_strings, | 3187 | .get_strings = qeth_core_get_strings, |
3190 | .get_ethtool_stats = qeth_core_get_ethtool_stats, | 3188 | .get_ethtool_stats = qeth_core_get_ethtool_stats, |
3191 | .get_sset_count = qeth_core_get_sset_count, | 3189 | .get_sset_count = qeth_core_get_sset_count, |
@@ -3226,6 +3224,8 @@ static const struct net_device_ops qeth_l3_netdev_ops = { | |||
3226 | .ndo_set_multicast_list = qeth_l3_set_multicast_list, | 3224 | .ndo_set_multicast_list = qeth_l3_set_multicast_list, |
3227 | .ndo_do_ioctl = qeth_l3_do_ioctl, | 3225 | .ndo_do_ioctl = qeth_l3_do_ioctl, |
3228 | .ndo_change_mtu = qeth_change_mtu, | 3226 | .ndo_change_mtu = qeth_change_mtu, |
3227 | .ndo_fix_features = qeth_l3_fix_features, | ||
3228 | .ndo_set_features = qeth_l3_set_features, | ||
3229 | .ndo_vlan_rx_register = qeth_l3_vlan_rx_register, | 3229 | .ndo_vlan_rx_register = qeth_l3_vlan_rx_register, |
3230 | .ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid, | 3230 | .ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid, |
3231 | .ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid, | 3231 | .ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid, |
@@ -3241,6 +3241,8 @@ static const struct net_device_ops qeth_l3_osa_netdev_ops = { | |||
3241 | .ndo_set_multicast_list = qeth_l3_set_multicast_list, | 3241 | .ndo_set_multicast_list = qeth_l3_set_multicast_list, |
3242 | .ndo_do_ioctl = qeth_l3_do_ioctl, | 3242 | .ndo_do_ioctl = qeth_l3_do_ioctl, |
3243 | .ndo_change_mtu = qeth_change_mtu, | 3243 | .ndo_change_mtu = qeth_change_mtu, |
3244 | .ndo_fix_features = qeth_l3_fix_features, | ||
3245 | .ndo_set_features = qeth_l3_set_features, | ||
3244 | .ndo_vlan_rx_register = qeth_l3_vlan_rx_register, | 3246 | .ndo_vlan_rx_register = qeth_l3_vlan_rx_register, |
3245 | .ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid, | 3247 | .ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid, |
3246 | .ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid, | 3248 | .ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid, |
@@ -3271,6 +3273,12 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) | |||
3271 | if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD)) | 3273 | if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD)) |
3272 | card->dev->dev_id = card->info.unique_id & | 3274 | card->dev->dev_id = card->info.unique_id & |
3273 | 0xffff; | 3275 | 0xffff; |
3276 | if (!card->info.guestlan) { | ||
3277 | card->dev->hw_features = NETIF_F_SG | | ||
3278 | NETIF_F_RXCSUM | NETIF_F_IP_CSUM | | ||
3279 | NETIF_F_TSO; | ||
3280 | card->dev->features = NETIF_F_RXCSUM; | ||
3281 | } | ||
3274 | } | 3282 | } |
3275 | } else if (card->info.type == QETH_CARD_TYPE_IQD) { | 3283 | } else if (card->info.type == QETH_CARD_TYPE_IQD) { |
3276 | card->dev = alloc_netdev(0, "hsi%d", ether_setup); | 3284 | card->dev = alloc_netdev(0, "hsi%d", ether_setup); |
@@ -3293,57 +3301,20 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) | |||
3293 | card->dev->gso_max_size = 15 * PAGE_SIZE; | 3301 | card->dev->gso_max_size = 15 * PAGE_SIZE; |
3294 | 3302 | ||
3295 | SET_NETDEV_DEV(card->dev, &card->gdev->dev); | 3303 | SET_NETDEV_DEV(card->dev, &card->gdev->dev); |
3304 | netif_napi_add(card->dev, &card->napi, qeth_l3_poll, QETH_NAPI_WEIGHT); | ||
3296 | return register_netdev(card->dev); | 3305 | return register_netdev(card->dev); |
3297 | } | 3306 | } |
3298 | 3307 | ||
3299 | static void qeth_l3_qdio_input_handler(struct ccw_device *ccwdev, | ||
3300 | unsigned int qdio_err, unsigned int queue, int first_element, | ||
3301 | int count, unsigned long card_ptr) | ||
3302 | { | ||
3303 | struct net_device *net_dev; | ||
3304 | struct qeth_card *card; | ||
3305 | struct qeth_qdio_buffer *buffer; | ||
3306 | int index; | ||
3307 | int i; | ||
3308 | |||
3309 | card = (struct qeth_card *) card_ptr; | ||
3310 | net_dev = card->dev; | ||
3311 | if (card->options.performance_stats) { | ||
3312 | card->perf_stats.inbound_cnt++; | ||
3313 | card->perf_stats.inbound_start_time = qeth_get_micros(); | ||
3314 | } | ||
3315 | if (qdio_err & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) { | ||
3316 | QETH_CARD_TEXT(card, 1, "qdinchk"); | ||
3317 | QETH_CARD_TEXT_(card, 1, "%04X%04X", | ||
3318 | first_element, count); | ||
3319 | QETH_CARD_TEXT_(card, 1, "%04X", queue); | ||
3320 | qeth_schedule_recovery(card); | ||
3321 | return; | ||
3322 | } | ||
3323 | for (i = first_element; i < (first_element + count); ++i) { | ||
3324 | index = i % QDIO_MAX_BUFFERS_PER_Q; | ||
3325 | buffer = &card->qdio.in_q->bufs[index]; | ||
3326 | if (!(qdio_err && | ||
3327 | qeth_check_qdio_errors(card, buffer->buffer, | ||
3328 | qdio_err, "qinerr"))) | ||
3329 | qeth_l3_process_inbound_buffer(card, buffer, index); | ||
3330 | /* clear buffer and give back to hardware */ | ||
3331 | qeth_put_buffer_pool_entry(card, buffer->pool_entry); | ||
3332 | qeth_queue_input_buffer(card, index); | ||
3333 | } | ||
3334 | if (card->options.performance_stats) | ||
3335 | card->perf_stats.inbound_time += qeth_get_micros() - | ||
3336 | card->perf_stats.inbound_start_time; | ||
3337 | } | ||
3338 | |||
3339 | static int qeth_l3_probe_device(struct ccwgroup_device *gdev) | 3308 | static int qeth_l3_probe_device(struct ccwgroup_device *gdev) |
3340 | { | 3309 | { |
3341 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 3310 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
3342 | 3311 | ||
3343 | qeth_l3_create_device_attributes(&gdev->dev); | 3312 | qeth_l3_create_device_attributes(&gdev->dev); |
3344 | card->options.layer2 = 0; | 3313 | card->options.layer2 = 0; |
3314 | card->info.hwtrap = 0; | ||
3315 | card->discipline.start_poll = qeth_qdio_start_poll; | ||
3345 | card->discipline.input_handler = (qdio_handler_t *) | 3316 | card->discipline.input_handler = (qdio_handler_t *) |
3346 | qeth_l3_qdio_input_handler; | 3317 | qeth_qdio_input_handler; |
3347 | card->discipline.output_handler = (qdio_handler_t *) | 3318 | card->discipline.output_handler = (qdio_handler_t *) |
3348 | qeth_qdio_output_handler; | 3319 | qeth_qdio_output_handler; |
3349 | card->discipline.recover = qeth_l3_recover; | 3320 | card->discipline.recover = qeth_l3_recover; |
@@ -3359,17 +3330,15 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev) | |||
3359 | qeth_set_allowed_threads(card, 0, 1); | 3330 | qeth_set_allowed_threads(card, 0, 1); |
3360 | wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); | 3331 | wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); |
3361 | 3332 | ||
3362 | if (cgdev->state == CCWGROUP_ONLINE) { | 3333 | if (cgdev->state == CCWGROUP_ONLINE) |
3363 | card->use_hard_stop = 1; | ||
3364 | qeth_l3_set_offline(cgdev); | 3334 | qeth_l3_set_offline(cgdev); |
3365 | } | ||
3366 | 3335 | ||
3367 | if (card->dev) { | 3336 | if (card->dev) { |
3368 | unregister_netdev(card->dev); | 3337 | unregister_netdev(card->dev); |
3369 | card->dev = NULL; | 3338 | card->dev = NULL; |
3370 | } | 3339 | } |
3371 | 3340 | ||
3372 | qeth_l3_clear_ip_list(card, 0, 0); | 3341 | qeth_l3_clear_ip_list(card, 0); |
3373 | qeth_l3_clear_ipato_list(card); | 3342 | qeth_l3_clear_ipato_list(card); |
3374 | return; | 3343 | return; |
3375 | } | 3344 | } |
@@ -3394,14 +3363,20 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
3394 | goto out_remove; | 3363 | goto out_remove; |
3395 | } | 3364 | } |
3396 | 3365 | ||
3397 | qeth_l3_query_ipassists(card, QETH_PROT_IPV4); | ||
3398 | |||
3399 | if (!card->dev && qeth_l3_setup_netdev(card)) { | 3366 | if (!card->dev && qeth_l3_setup_netdev(card)) { |
3400 | rc = -ENODEV; | 3367 | rc = -ENODEV; |
3401 | goto out_remove; | 3368 | goto out_remove; |
3402 | } | 3369 | } |
3403 | 3370 | ||
3371 | if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) { | ||
3372 | if (card->info.hwtrap && | ||
3373 | qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM)) | ||
3374 | card->info.hwtrap = 0; | ||
3375 | } else | ||
3376 | card->info.hwtrap = 0; | ||
3377 | |||
3404 | card->state = CARD_STATE_HARDSETUP; | 3378 | card->state = CARD_STATE_HARDSETUP; |
3379 | memset(&card->rx, 0, sizeof(struct qeth_rx)); | ||
3405 | qeth_print_status_message(card); | 3380 | qeth_print_status_message(card); |
3406 | 3381 | ||
3407 | /* softsetup */ | 3382 | /* softsetup */ |
@@ -3414,13 +3389,14 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
3414 | dev_warn(&card->gdev->dev, | 3389 | dev_warn(&card->gdev->dev, |
3415 | "The LAN is offline\n"); | 3390 | "The LAN is offline\n"); |
3416 | card->lan_online = 0; | 3391 | card->lan_online = 0; |
3417 | goto out; | 3392 | goto contin; |
3418 | } | 3393 | } |
3419 | rc = -ENODEV; | 3394 | rc = -ENODEV; |
3420 | goto out_remove; | 3395 | goto out_remove; |
3421 | } else | 3396 | } else |
3422 | card->lan_online = 1; | 3397 | card->lan_online = 1; |
3423 | 3398 | ||
3399 | contin: | ||
3424 | rc = qeth_l3_setadapter_parms(card); | 3400 | rc = qeth_l3_setadapter_parms(card); |
3425 | if (rc) | 3401 | if (rc) |
3426 | QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc); | 3402 | QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc); |
@@ -3428,7 +3404,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
3428 | rc = qeth_l3_start_ipassists(card); | 3404 | rc = qeth_l3_start_ipassists(card); |
3429 | if (rc) | 3405 | if (rc) |
3430 | QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc); | 3406 | QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc); |
3431 | qeth_l3_set_large_send(card, card->options.large_send); | ||
3432 | rc = qeth_l3_setrouting_v4(card); | 3407 | rc = qeth_l3_setrouting_v4(card); |
3433 | if (rc) | 3408 | if (rc) |
3434 | QETH_DBF_TEXT_(SETUP, 2, "4err%d", rc); | 3409 | QETH_DBF_TEXT_(SETUP, 2, "4err%d", rc); |
@@ -3445,13 +3420,16 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
3445 | goto out_remove; | 3420 | goto out_remove; |
3446 | } | 3421 | } |
3447 | card->state = CARD_STATE_SOFTSETUP; | 3422 | card->state = CARD_STATE_SOFTSETUP; |
3448 | netif_carrier_on(card->dev); | ||
3449 | 3423 | ||
3450 | qeth_set_allowed_threads(card, 0xffffffff, 0); | 3424 | qeth_set_allowed_threads(card, 0xffffffff, 0); |
3451 | qeth_l3_set_ip_addr_list(card); | 3425 | qeth_l3_set_ip_addr_list(card); |
3426 | if (card->lan_online) | ||
3427 | netif_carrier_on(card->dev); | ||
3428 | else | ||
3429 | netif_carrier_off(card->dev); | ||
3452 | if (recover_flag == CARD_STATE_RECOVER) { | 3430 | if (recover_flag == CARD_STATE_RECOVER) { |
3453 | if (recovery_mode) | 3431 | if (recovery_mode) |
3454 | qeth_l3_open(card->dev); | 3432 | __qeth_l3_open(card->dev); |
3455 | else { | 3433 | else { |
3456 | rtnl_lock(); | 3434 | rtnl_lock(); |
3457 | dev_open(card->dev); | 3435 | dev_open(card->dev); |
@@ -3461,12 +3439,10 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
3461 | } | 3439 | } |
3462 | /* let user_space know that device is online */ | 3440 | /* let user_space know that device is online */ |
3463 | kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); | 3441 | kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); |
3464 | out: | ||
3465 | mutex_unlock(&card->conf_mutex); | 3442 | mutex_unlock(&card->conf_mutex); |
3466 | mutex_unlock(&card->discipline_mutex); | 3443 | mutex_unlock(&card->discipline_mutex); |
3467 | return 0; | 3444 | return 0; |
3468 | out_remove: | 3445 | out_remove: |
3469 | card->use_hard_stop = 1; | ||
3470 | qeth_l3_stop_card(card, 0); | 3446 | qeth_l3_stop_card(card, 0); |
3471 | ccw_device_set_offline(CARD_DDEV(card)); | 3447 | ccw_device_set_offline(CARD_DDEV(card)); |
3472 | ccw_device_set_offline(CARD_WDEV(card)); | 3448 | ccw_device_set_offline(CARD_WDEV(card)); |
@@ -3500,6 +3476,10 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, | |||
3500 | if (card->dev && netif_carrier_ok(card->dev)) | 3476 | if (card->dev && netif_carrier_ok(card->dev)) |
3501 | netif_carrier_off(card->dev); | 3477 | netif_carrier_off(card->dev); |
3502 | recover_flag = card->state; | 3478 | recover_flag = card->state; |
3479 | if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) { | ||
3480 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | ||
3481 | card->info.hwtrap = 1; | ||
3482 | } | ||
3503 | qeth_l3_stop_card(card, recovery_mode); | 3483 | qeth_l3_stop_card(card, recovery_mode); |
3504 | rc = ccw_device_set_offline(CARD_DDEV(card)); | 3484 | rc = ccw_device_set_offline(CARD_DDEV(card)); |
3505 | rc2 = ccw_device_set_offline(CARD_WDEV(card)); | 3485 | rc2 = ccw_device_set_offline(CARD_WDEV(card)); |
@@ -3535,12 +3515,8 @@ static int qeth_l3_recover(void *ptr) | |||
3535 | QETH_CARD_TEXT(card, 2, "recover2"); | 3515 | QETH_CARD_TEXT(card, 2, "recover2"); |
3536 | dev_warn(&card->gdev->dev, | 3516 | dev_warn(&card->gdev->dev, |
3537 | "A recovery process has been started for the device\n"); | 3517 | "A recovery process has been started for the device\n"); |
3538 | card->use_hard_stop = 1; | ||
3539 | __qeth_l3_set_offline(card->gdev, 1); | 3518 | __qeth_l3_set_offline(card->gdev, 1); |
3540 | rc = __qeth_l3_set_online(card->gdev, 1); | 3519 | rc = __qeth_l3_set_online(card->gdev, 1); |
3541 | /* don't run another scheduled recovery */ | ||
3542 | qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); | ||
3543 | qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); | ||
3544 | if (!rc) | 3520 | if (!rc) |
3545 | dev_info(&card->gdev->dev, | 3521 | dev_info(&card->gdev->dev, |
3546 | "Device successfully recovered!\n"); | 3522 | "Device successfully recovered!\n"); |
@@ -3551,13 +3527,16 @@ static int qeth_l3_recover(void *ptr) | |||
3551 | dev_warn(&card->gdev->dev, "The qeth device driver " | 3527 | dev_warn(&card->gdev->dev, "The qeth device driver " |
3552 | "failed to recover an error on the device\n"); | 3528 | "failed to recover an error on the device\n"); |
3553 | } | 3529 | } |
3530 | qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); | ||
3531 | qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); | ||
3554 | return 0; | 3532 | return 0; |
3555 | } | 3533 | } |
3556 | 3534 | ||
3557 | static void qeth_l3_shutdown(struct ccwgroup_device *gdev) | 3535 | static void qeth_l3_shutdown(struct ccwgroup_device *gdev) |
3558 | { | 3536 | { |
3559 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 3537 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
3560 | qeth_l3_clear_ip_list(card, 0, 0); | 3538 | if ((gdev->state == CCWGROUP_ONLINE) && card->info.hwtrap) |
3539 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | ||
3561 | qeth_qdio_clear_card(card, 0); | 3540 | qeth_qdio_clear_card(card, 0); |
3562 | qeth_clear_qdio_buffers(card); | 3541 | qeth_clear_qdio_buffers(card); |
3563 | } | 3542 | } |
@@ -3573,7 +3552,8 @@ static int qeth_l3_pm_suspend(struct ccwgroup_device *gdev) | |||
3573 | if (gdev->state == CCWGROUP_OFFLINE) | 3552 | if (gdev->state == CCWGROUP_OFFLINE) |
3574 | return 0; | 3553 | return 0; |
3575 | if (card->state == CARD_STATE_UP) { | 3554 | if (card->state == CARD_STATE_UP) { |
3576 | card->use_hard_stop = 1; | 3555 | if (card->info.hwtrap) |
3556 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | ||
3577 | __qeth_l3_set_offline(card->gdev, 1); | 3557 | __qeth_l3_set_offline(card->gdev, 1); |
3578 | } else | 3558 | } else |
3579 | __qeth_l3_set_offline(card->gdev, 0); | 3559 | __qeth_l3_set_offline(card->gdev, 0); |