diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/char/raw3270.c | 4 | ||||
-rw-r--r-- | drivers/s390/net/lcs.c | 4 | ||||
-rw-r--r-- | drivers/s390/net/qeth.h | 77 | ||||
-rw-r--r-- | drivers/s390/net/qeth_eddp.c | 3 | ||||
-rw-r--r-- | drivers/s390/net/qeth_main.c | 316 | ||||
-rw-r--r-- | drivers/s390/net/qeth_mpc.c | 4 | ||||
-rw-r--r-- | drivers/s390/net/qeth_mpc.h | 15 | ||||
-rw-r--r-- | drivers/s390/net/qeth_proc.c | 250 | ||||
-rw-r--r-- | drivers/s390/net/qeth_sys.c | 10 | ||||
-rw-r--r-- | drivers/s390/net/qeth_tso.h | 6 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 14 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_dbf.c | 4 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 94 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 110 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 2 |
15 files changed, 463 insertions, 450 deletions
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index f5b7d360fc10..1026f2bc3185 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c | |||
@@ -1179,12 +1179,12 @@ raw3270_create_attributes(struct raw3270 *rp) | |||
1179 | //FIXME: check return code | 1179 | //FIXME: check return code |
1180 | sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group); | 1180 | sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group); |
1181 | rp->clttydev = | 1181 | rp->clttydev = |
1182 | class_device_create(class3270, | 1182 | class_device_create(class3270, NULL, |
1183 | MKDEV(IBM_TTY3270_MAJOR, rp->minor), | 1183 | MKDEV(IBM_TTY3270_MAJOR, rp->minor), |
1184 | &rp->cdev->dev, "tty%s", | 1184 | &rp->cdev->dev, "tty%s", |
1185 | rp->cdev->dev.bus_id); | 1185 | rp->cdev->dev.bus_id); |
1186 | rp->cltubdev = | 1186 | rp->cltubdev = |
1187 | class_device_create(class3270, | 1187 | class_device_create(class3270, NULL, |
1188 | MKDEV(IBM_FS3270_MAJOR, rp->minor), | 1188 | MKDEV(IBM_FS3270_MAJOR, rp->minor), |
1189 | &rp->cdev->dev, "tub%s", | 1189 | &rp->cdev->dev, "tub%s", |
1190 | rp->cdev->dev.bus_id); | 1190 | rp->cdev->dev.bus_id); |
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 1c8ad2fcad8a..da8c515743e8 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * Author(s): Original Code written by | 8 | * Author(s): Original Code written by |
9 | * DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) | 9 | * DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) |
10 | * Rewritten by | 10 | * Rewritten by |
11 | * Frank Pavlic (pavlic@de.ibm.com) and | 11 | * Frank Pavlic (fpavlic@de.ibm.com) and |
12 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 12 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
13 | * | 13 | * |
14 | * $Revision: 1.99 $ $Date: 2005/05/11 08:10:17 $ | 14 | * $Revision: 1.99 $ $Date: 2005/05/11 08:10:17 $ |
@@ -2342,6 +2342,6 @@ __exit lcs_cleanup_module(void) | |||
2342 | module_init(lcs_init_module); | 2342 | module_init(lcs_init_module); |
2343 | module_exit(lcs_cleanup_module); | 2343 | module_exit(lcs_cleanup_module); |
2344 | 2344 | ||
2345 | MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>"); | 2345 | MODULE_AUTHOR("Frank Pavlic <fpavlic@de.ibm.com>"); |
2346 | MODULE_LICENSE("GPL"); | 2346 | MODULE_LICENSE("GPL"); |
2347 | 2347 | ||
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index 38a2441564d7..d238c7ed103b 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/trdevice.h> | 8 | #include <linux/trdevice.h> |
9 | #include <linux/etherdevice.h> | 9 | #include <linux/etherdevice.h> |
10 | #include <linux/if_vlan.h> | 10 | #include <linux/if_vlan.h> |
11 | #include <linux/ctype.h> | ||
11 | 12 | ||
12 | #include <net/ipv6.h> | 13 | #include <net/ipv6.h> |
13 | #include <linux/in6.h> | 14 | #include <linux/in6.h> |
@@ -24,7 +25,7 @@ | |||
24 | 25 | ||
25 | #include "qeth_mpc.h" | 26 | #include "qeth_mpc.h" |
26 | 27 | ||
27 | #define VERSION_QETH_H "$Revision: 1.142 $" | 28 | #define VERSION_QETH_H "$Revision: 1.152 $" |
28 | 29 | ||
29 | #ifdef CONFIG_QETH_IPV6 | 30 | #ifdef CONFIG_QETH_IPV6 |
30 | #define QETH_VERSION_IPV6 ":IPv6" | 31 | #define QETH_VERSION_IPV6 ":IPv6" |
@@ -718,8 +719,6 @@ struct qeth_reply { | |||
718 | atomic_t refcnt; | 719 | atomic_t refcnt; |
719 | }; | 720 | }; |
720 | 721 | ||
721 | #define QETH_BROADCAST_WITH_ECHO 1 | ||
722 | #define QETH_BROADCAST_WITHOUT_ECHO 2 | ||
723 | 722 | ||
724 | struct qeth_card_blkt { | 723 | struct qeth_card_blkt { |
725 | int time_total; | 724 | int time_total; |
@@ -727,8 +726,10 @@ struct qeth_card_blkt { | |||
727 | int inter_packet_jumbo; | 726 | int inter_packet_jumbo; |
728 | }; | 727 | }; |
729 | 728 | ||
730 | 729 | #define QETH_BROADCAST_WITH_ECHO 0x01 | |
731 | 730 | #define QETH_BROADCAST_WITHOUT_ECHO 0x02 | |
731 | #define QETH_LAYER2_MAC_READ 0x01 | ||
732 | #define QETH_LAYER2_MAC_REGISTERED 0x02 | ||
732 | struct qeth_card_info { | 733 | struct qeth_card_info { |
733 | unsigned short unit_addr2; | 734 | unsigned short unit_addr2; |
734 | unsigned short cula; | 735 | unsigned short cula; |
@@ -736,7 +737,7 @@ struct qeth_card_info { | |||
736 | __u16 func_level; | 737 | __u16 func_level; |
737 | char mcl_level[QETH_MCL_LENGTH + 1]; | 738 | char mcl_level[QETH_MCL_LENGTH + 1]; |
738 | int guestlan; | 739 | int guestlan; |
739 | int layer2_mac_registered; | 740 | int mac_bits; |
740 | int portname_required; | 741 | int portname_required; |
741 | int portno; | 742 | int portno; |
742 | char portname[9]; | 743 | char portname[9]; |
@@ -749,6 +750,7 @@ struct qeth_card_info { | |||
749 | int unique_id; | 750 | int unique_id; |
750 | struct qeth_card_blkt blkt; | 751 | struct qeth_card_blkt blkt; |
751 | __u32 csum_mask; | 752 | __u32 csum_mask; |
753 | enum qeth_ipa_promisc_modes promisc_mode; | ||
752 | }; | 754 | }; |
753 | 755 | ||
754 | struct qeth_card_options { | 756 | struct qeth_card_options { |
@@ -775,6 +777,7 @@ struct qeth_card_options { | |||
775 | enum qeth_threads { | 777 | enum qeth_threads { |
776 | QETH_SET_IP_THREAD = 1, | 778 | QETH_SET_IP_THREAD = 1, |
777 | QETH_RECOVER_THREAD = 2, | 779 | QETH_RECOVER_THREAD = 2, |
780 | QETH_SET_PROMISC_MODE_THREAD = 4, | ||
778 | }; | 781 | }; |
779 | 782 | ||
780 | struct qeth_osn_info { | 783 | struct qeth_osn_info { |
@@ -1074,6 +1077,26 @@ qeth_get_qdio_q_format(struct qeth_card *card) | |||
1074 | } | 1077 | } |
1075 | } | 1078 | } |
1076 | 1079 | ||
1080 | static inline int | ||
1081 | qeth_isdigit(char * buf) | ||
1082 | { | ||
1083 | while (*buf) { | ||
1084 | if (!isdigit(*buf++)) | ||
1085 | return 0; | ||
1086 | } | ||
1087 | return 1; | ||
1088 | } | ||
1089 | |||
1090 | static inline int | ||
1091 | qeth_isxdigit(char * buf) | ||
1092 | { | ||
1093 | while (*buf) { | ||
1094 | if (!isxdigit(*buf++)) | ||
1095 | return 0; | ||
1096 | } | ||
1097 | return 1; | ||
1098 | } | ||
1099 | |||
1077 | static inline void | 1100 | static inline void |
1078 | qeth_ipaddr4_to_string(const __u8 *addr, char *buf) | 1101 | qeth_ipaddr4_to_string(const __u8 *addr, char *buf) |
1079 | { | 1102 | { |
@@ -1090,18 +1113,27 @@ qeth_string_to_ipaddr4(const char *buf, __u8 *addr) | |||
1090 | int i; | 1113 | int i; |
1091 | 1114 | ||
1092 | start = buf; | 1115 | start = buf; |
1093 | for (i = 0; i < 3; i++) { | 1116 | for (i = 0; i < 4; i++) { |
1094 | if (!(end = strchr(start, '.'))) | 1117 | if (i == 3) { |
1118 | end = strchr(start,0xa); | ||
1119 | if (end) | ||
1120 | len = end - start; | ||
1121 | else | ||
1122 | len = strlen(start); | ||
1123 | } | ||
1124 | else { | ||
1125 | end = strchr(start, '.'); | ||
1126 | len = end - start; | ||
1127 | } | ||
1128 | if ((len <= 0) || (len > 3)) | ||
1095 | return -EINVAL; | 1129 | return -EINVAL; |
1096 | len = end - start; | ||
1097 | memset(abuf, 0, 4); | 1130 | memset(abuf, 0, 4); |
1098 | strncpy(abuf, start, len); | 1131 | strncpy(abuf, start, len); |
1132 | if (!qeth_isdigit(abuf)) | ||
1133 | return -EINVAL; | ||
1099 | addr[i] = simple_strtoul(abuf, &tmp, 10); | 1134 | addr[i] = simple_strtoul(abuf, &tmp, 10); |
1100 | start = end + 1; | 1135 | start = end + 1; |
1101 | } | 1136 | } |
1102 | memset(abuf, 0, 4); | ||
1103 | strcpy(abuf, start); | ||
1104 | addr[3] = simple_strtoul(abuf, &tmp, 10); | ||
1105 | return 0; | 1137 | return 0; |
1106 | } | 1138 | } |
1107 | 1139 | ||
@@ -1128,18 +1160,27 @@ qeth_string_to_ipaddr6(const char *buf, __u8 *addr) | |||
1128 | 1160 | ||
1129 | tmp_addr = (u16 *)addr; | 1161 | tmp_addr = (u16 *)addr; |
1130 | start = buf; | 1162 | start = buf; |
1131 | for (i = 0; i < 7; i++) { | 1163 | for (i = 0; i < 8; i++) { |
1132 | if (!(end = strchr(start, ':'))) | 1164 | if (i == 7) { |
1165 | end = strchr(start,0xa); | ||
1166 | if (end) | ||
1167 | len = end - start; | ||
1168 | else | ||
1169 | len = strlen(start); | ||
1170 | } | ||
1171 | else { | ||
1172 | end = strchr(start, ':'); | ||
1173 | len = end - start; | ||
1174 | } | ||
1175 | if ((len <= 0) || (len > 4)) | ||
1133 | return -EINVAL; | 1176 | return -EINVAL; |
1134 | len = end - start; | ||
1135 | memset(abuf, 0, 5); | 1177 | memset(abuf, 0, 5); |
1136 | strncpy(abuf, start, len); | 1178 | strncpy(abuf, start, len); |
1179 | if (!qeth_isxdigit(abuf)) | ||
1180 | return -EINVAL; | ||
1137 | tmp_addr[i] = simple_strtoul(abuf, &tmp, 16); | 1181 | tmp_addr[i] = simple_strtoul(abuf, &tmp, 16); |
1138 | start = end + 1; | 1182 | start = end + 1; |
1139 | } | 1183 | } |
1140 | memset(abuf, 0, 5); | ||
1141 | strcpy(abuf, start); | ||
1142 | tmp_addr[7] = simple_strtoul(abuf, &tmp, 16); | ||
1143 | return 0; | 1184 | return 0; |
1144 | } | 1185 | } |
1145 | 1186 | ||
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c index 011915d5e243..f94f1f25eec6 100644 --- a/drivers/s390/net/qeth_eddp.c +++ b/drivers/s390/net/qeth_eddp.c | |||
@@ -62,7 +62,8 @@ qeth_eddp_free_context(struct qeth_eddp_context *ctx) | |||
62 | for (i = 0; i < ctx->num_pages; ++i) | 62 | for (i = 0; i < ctx->num_pages; ++i) |
63 | free_page((unsigned long)ctx->pages[i]); | 63 | free_page((unsigned long)ctx->pages[i]); |
64 | kfree(ctx->pages); | 64 | kfree(ctx->pages); |
65 | kfree(ctx->elements); | 65 | if (ctx->elements != NULL) |
66 | kfree(ctx->elements); | ||
66 | kfree(ctx); | 67 | kfree(ctx); |
67 | } | 68 | } |
68 | 69 | ||
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 692003c9f896..f8f55cc468ba 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * | 2 | * |
3 | * linux/drivers/s390/net/qeth_main.c ($Revision: 1.224 $) | 3 | * linux/drivers/s390/net/qeth_main.c ($Revision: 1.251 $) |
4 | * | 4 | * |
5 | * Linux on zSeries OSA Express and HiperSockets support | 5 | * Linux on zSeries OSA Express and HiperSockets support |
6 | * | 6 | * |
@@ -9,10 +9,10 @@ | |||
9 | * Author(s): Original Code written by | 9 | * Author(s): Original Code written by |
10 | * Utz Bacher (utz.bacher@de.ibm.com) | 10 | * Utz Bacher (utz.bacher@de.ibm.com) |
11 | * Rewritten by | 11 | * Rewritten by |
12 | * Frank Pavlic (pavlic@de.ibm.com) and | 12 | * Frank Pavlic (fpavlic@de.ibm.com) and |
13 | * Thomas Spatzier <tspat@de.ibm.com> | 13 | * Thomas Spatzier <tspat@de.ibm.com> |
14 | * | 14 | * |
15 | * $Revision: 1.224 $ $Date: 2005/05/04 20:19:18 $ | 15 | * $Revision: 1.251 $ $Date: 2005/05/04 20:19:18 $ |
16 | * | 16 | * |
17 | * This program is free software; you can redistribute it and/or modify | 17 | * This program is free software; you can redistribute it and/or modify |
18 | * it under the terms of the GNU General Public License as published by | 18 | * it under the terms of the GNU General Public License as published by |
@@ -72,7 +72,7 @@ | |||
72 | #include "qeth_eddp.h" | 72 | #include "qeth_eddp.h" |
73 | #include "qeth_tso.h" | 73 | #include "qeth_tso.h" |
74 | 74 | ||
75 | #define VERSION_QETH_C "$Revision: 1.224 $" | 75 | #define VERSION_QETH_C "$Revision: 1.251 $" |
76 | static const char *version = "qeth S/390 OSA-Express driver"; | 76 | static const char *version = "qeth S/390 OSA-Express driver"; |
77 | 77 | ||
78 | /** | 78 | /** |
@@ -160,6 +160,9 @@ static void | |||
160 | qeth_set_multicast_list(struct net_device *); | 160 | qeth_set_multicast_list(struct net_device *); |
161 | 161 | ||
162 | static void | 162 | static void |
163 | qeth_setadp_promisc_mode(struct qeth_card *); | ||
164 | |||
165 | static void | ||
163 | qeth_notify_processes(void) | 166 | qeth_notify_processes(void) |
164 | { | 167 | { |
165 | /*notify all registered processes */ | 168 | /*notify all registered processes */ |
@@ -515,7 +518,8 @@ __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode) | |||
515 | 518 | ||
516 | QETH_DBF_TEXT(setup, 3, "setoffl"); | 519 | QETH_DBF_TEXT(setup, 3, "setoffl"); |
517 | QETH_DBF_HEX(setup, 3, &card, sizeof(void *)); | 520 | QETH_DBF_HEX(setup, 3, &card, sizeof(void *)); |
518 | 521 | ||
522 | netif_carrier_off(card->dev); | ||
519 | recover_flag = card->state; | 523 | recover_flag = card->state; |
520 | if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){ | 524 | if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){ |
521 | PRINT_WARN("Stopping card %s interrupted by user!\n", | 525 | PRINT_WARN("Stopping card %s interrupted by user!\n", |
@@ -602,11 +606,20 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, | |||
602 | int found = 0; | 606 | int found = 0; |
603 | 607 | ||
604 | list_for_each_entry(addr, &card->ip_list, entry) { | 608 | list_for_each_entry(addr, &card->ip_list, entry) { |
609 | if (card->options.layer2) { | ||
610 | if ((addr->type == todo->type) && | ||
611 | (memcmp(&addr->mac, &todo->mac, | ||
612 | OSA_ADDR_LEN) == 0)) { | ||
613 | found = 1; | ||
614 | break; | ||
615 | } | ||
616 | continue; | ||
617 | } | ||
605 | if ((addr->proto == QETH_PROT_IPV4) && | 618 | if ((addr->proto == QETH_PROT_IPV4) && |
606 | (todo->proto == QETH_PROT_IPV4) && | 619 | (todo->proto == QETH_PROT_IPV4) && |
607 | (addr->type == todo->type) && | 620 | (addr->type == todo->type) && |
608 | (addr->u.a4.addr == todo->u.a4.addr) && | 621 | (addr->u.a4.addr == todo->u.a4.addr) && |
609 | (addr->u.a4.mask == todo->u.a4.mask) ){ | 622 | (addr->u.a4.mask == todo->u.a4.mask)) { |
610 | found = 1; | 623 | found = 1; |
611 | break; | 624 | break; |
612 | } | 625 | } |
@@ -615,12 +628,12 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, | |||
615 | (addr->type == todo->type) && | 628 | (addr->type == todo->type) && |
616 | (addr->u.a6.pfxlen == todo->u.a6.pfxlen) && | 629 | (addr->u.a6.pfxlen == todo->u.a6.pfxlen) && |
617 | (memcmp(&addr->u.a6.addr, &todo->u.a6.addr, | 630 | (memcmp(&addr->u.a6.addr, &todo->u.a6.addr, |
618 | sizeof(struct in6_addr)) == 0)) { | 631 | sizeof(struct in6_addr)) == 0)) { |
619 | found = 1; | 632 | found = 1; |
620 | break; | 633 | break; |
621 | } | 634 | } |
622 | } | 635 | } |
623 | if (found){ | 636 | if (found) { |
624 | addr->users += todo->users; | 637 | addr->users += todo->users; |
625 | if (addr->users <= 0){ | 638 | if (addr->users <= 0){ |
626 | *__addr = addr; | 639 | *__addr = addr; |
@@ -632,7 +645,7 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, | |||
632 | return 0; | 645 | return 0; |
633 | } | 646 | } |
634 | } | 647 | } |
635 | if (todo->users > 0){ | 648 | if (todo->users > 0) { |
636 | /* for VIPA and RXIP limit refcount to 1 */ | 649 | /* for VIPA and RXIP limit refcount to 1 */ |
637 | if (todo->type != QETH_IP_TYPE_NORMAL) | 650 | if (todo->type != QETH_IP_TYPE_NORMAL) |
638 | todo->users = 1; | 651 | todo->users = 1; |
@@ -682,12 +695,22 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) | |||
682 | if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) && | 695 | if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) && |
683 | (tmp->type == QETH_IP_TYPE_DEL_ALL_MC)) | 696 | (tmp->type == QETH_IP_TYPE_DEL_ALL_MC)) |
684 | return 0; | 697 | return 0; |
698 | if (card->options.layer2) { | ||
699 | if ((tmp->type == addr->type) && | ||
700 | (tmp->is_multicast == addr->is_multicast) && | ||
701 | (memcmp(&tmp->mac, &addr->mac, | ||
702 | OSA_ADDR_LEN) == 0)) { | ||
703 | found = 1; | ||
704 | break; | ||
705 | } | ||
706 | continue; | ||
707 | } | ||
685 | if ((tmp->proto == QETH_PROT_IPV4) && | 708 | if ((tmp->proto == QETH_PROT_IPV4) && |
686 | (addr->proto == QETH_PROT_IPV4) && | 709 | (addr->proto == QETH_PROT_IPV4) && |
687 | (tmp->type == addr->type) && | 710 | (tmp->type == addr->type) && |
688 | (tmp->is_multicast == addr->is_multicast) && | 711 | (tmp->is_multicast == addr->is_multicast) && |
689 | (tmp->u.a4.addr == addr->u.a4.addr) && | 712 | (tmp->u.a4.addr == addr->u.a4.addr) && |
690 | (tmp->u.a4.mask == addr->u.a4.mask) ){ | 713 | (tmp->u.a4.mask == addr->u.a4.mask)) { |
691 | found = 1; | 714 | found = 1; |
692 | break; | 715 | break; |
693 | } | 716 | } |
@@ -697,7 +720,7 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) | |||
697 | (tmp->is_multicast == addr->is_multicast) && | 720 | (tmp->is_multicast == addr->is_multicast) && |
698 | (tmp->u.a6.pfxlen == addr->u.a6.pfxlen) && | 721 | (tmp->u.a6.pfxlen == addr->u.a6.pfxlen) && |
699 | (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr, | 722 | (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr, |
700 | sizeof(struct in6_addr)) == 0) ){ | 723 | sizeof(struct in6_addr)) == 0)) { |
701 | found = 1; | 724 | found = 1; |
702 | break; | 725 | break; |
703 | } | 726 | } |
@@ -707,7 +730,7 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) | |||
707 | tmp->users += addr->users; | 730 | tmp->users += addr->users; |
708 | else | 731 | else |
709 | tmp->users += add? 1:-1; | 732 | tmp->users += add? 1:-1; |
710 | if (tmp->users == 0){ | 733 | if (tmp->users == 0) { |
711 | list_del(&tmp->entry); | 734 | list_del(&tmp->entry); |
712 | kfree(tmp); | 735 | kfree(tmp); |
713 | } | 736 | } |
@@ -738,12 +761,15 @@ qeth_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr) | |||
738 | unsigned long flags; | 761 | unsigned long flags; |
739 | int rc = 0; | 762 | int rc = 0; |
740 | 763 | ||
741 | QETH_DBF_TEXT(trace,4,"delip"); | 764 | QETH_DBF_TEXT(trace, 4, "delip"); |
742 | if (addr->proto == QETH_PROT_IPV4) | 765 | |
743 | QETH_DBF_HEX(trace,4,&addr->u.a4.addr,4); | 766 | if (card->options.layer2) |
767 | QETH_DBF_HEX(trace, 4, &addr->mac, 6); | ||
768 | else if (addr->proto == QETH_PROT_IPV4) | ||
769 | QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4); | ||
744 | else { | 770 | else { |
745 | QETH_DBF_HEX(trace,4,&addr->u.a6.addr,8); | 771 | QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8); |
746 | QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+8,8); | 772 | QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8); |
747 | } | 773 | } |
748 | spin_lock_irqsave(&card->ip_lock, flags); | 774 | spin_lock_irqsave(&card->ip_lock, flags); |
749 | rc = __qeth_insert_ip_todo(card, addr, 0); | 775 | rc = __qeth_insert_ip_todo(card, addr, 0); |
@@ -757,12 +783,14 @@ qeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr) | |||
757 | unsigned long flags; | 783 | unsigned long flags; |
758 | int rc = 0; | 784 | int rc = 0; |
759 | 785 | ||
760 | QETH_DBF_TEXT(trace,4,"addip"); | 786 | QETH_DBF_TEXT(trace, 4, "addip"); |
761 | if (addr->proto == QETH_PROT_IPV4) | 787 | if (card->options.layer2) |
762 | QETH_DBF_HEX(trace,4,&addr->u.a4.addr,4); | 788 | QETH_DBF_HEX(trace, 4, &addr->mac, 6); |
789 | else if (addr->proto == QETH_PROT_IPV4) | ||
790 | QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4); | ||
763 | else { | 791 | else { |
764 | QETH_DBF_HEX(trace,4,&addr->u.a6.addr,8); | 792 | QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8); |
765 | QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+8,8); | 793 | QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8); |
766 | } | 794 | } |
767 | spin_lock_irqsave(&card->ip_lock, flags); | 795 | spin_lock_irqsave(&card->ip_lock, flags); |
768 | rc = __qeth_insert_ip_todo(card, addr, 1); | 796 | rc = __qeth_insert_ip_todo(card, addr, 1); |
@@ -775,7 +803,7 @@ __qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags) | |||
775 | { | 803 | { |
776 | struct qeth_ipaddr *addr, *tmp; | 804 | struct qeth_ipaddr *addr, *tmp; |
777 | int rc; | 805 | int rc; |
778 | 806 | again: | |
779 | list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) { | 807 | list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) { |
780 | if (addr->is_multicast) { | 808 | if (addr->is_multicast) { |
781 | spin_unlock_irqrestore(&card->ip_lock, *flags); | 809 | spin_unlock_irqrestore(&card->ip_lock, *flags); |
@@ -784,6 +812,7 @@ __qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags) | |||
784 | if (!rc) { | 812 | if (!rc) { |
785 | list_del(&addr->entry); | 813 | list_del(&addr->entry); |
786 | kfree(addr); | 814 | kfree(addr); |
815 | goto again; | ||
787 | } | 816 | } |
788 | } | 817 | } |
789 | } | 818 | } |
@@ -851,6 +880,7 @@ qeth_set_ip_addr_list(struct qeth_card *card) | |||
851 | 880 | ||
852 | static void qeth_delete_mc_addresses(struct qeth_card *); | 881 | static void qeth_delete_mc_addresses(struct qeth_card *); |
853 | static void qeth_add_multicast_ipv4(struct qeth_card *); | 882 | static void qeth_add_multicast_ipv4(struct qeth_card *); |
883 | static void qeth_layer2_add_multicast(struct qeth_card *); | ||
854 | #ifdef CONFIG_QETH_IPV6 | 884 | #ifdef CONFIG_QETH_IPV6 |
855 | static void qeth_add_multicast_ipv6(struct qeth_card *); | 885 | static void qeth_add_multicast_ipv6(struct qeth_card *); |
856 | #endif | 886 | #endif |
@@ -939,6 +969,24 @@ qeth_register_ip_addresses(void *ptr) | |||
939 | return 0; | 969 | return 0; |
940 | } | 970 | } |
941 | 971 | ||
972 | /* | ||
973 | * Drive the SET_PROMISC_MODE thread | ||
974 | */ | ||
975 | static int | ||
976 | qeth_set_promisc_mode(void *ptr) | ||
977 | { | ||
978 | struct qeth_card *card = (struct qeth_card *) ptr; | ||
979 | |||
980 | daemonize("qeth_setprm"); | ||
981 | QETH_DBF_TEXT(trace,4,"setprm1"); | ||
982 | if (!qeth_do_run_thread(card, QETH_SET_PROMISC_MODE_THREAD)) | ||
983 | return 0; | ||
984 | QETH_DBF_TEXT(trace,4,"setprm2"); | ||
985 | qeth_setadp_promisc_mode(card); | ||
986 | qeth_clear_thread_running_bit(card, QETH_SET_PROMISC_MODE_THREAD); | ||
987 | return 0; | ||
988 | } | ||
989 | |||
942 | static int | 990 | static int |
943 | qeth_recover(void *ptr) | 991 | qeth_recover(void *ptr) |
944 | { | 992 | { |
@@ -973,7 +1021,6 @@ void | |||
973 | qeth_schedule_recovery(struct qeth_card *card) | 1021 | qeth_schedule_recovery(struct qeth_card *card) |
974 | { | 1022 | { |
975 | QETH_DBF_TEXT(trace,2,"startrec"); | 1023 | QETH_DBF_TEXT(trace,2,"startrec"); |
976 | |||
977 | if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0) | 1024 | if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0) |
978 | schedule_work(&card->kernel_thread_starter); | 1025 | schedule_work(&card->kernel_thread_starter); |
979 | } | 1026 | } |
@@ -1005,6 +1052,8 @@ qeth_start_kernel_thread(struct qeth_card *card) | |||
1005 | 1052 | ||
1006 | if (qeth_do_start_thread(card, QETH_SET_IP_THREAD)) | 1053 | if (qeth_do_start_thread(card, QETH_SET_IP_THREAD)) |
1007 | kernel_thread(qeth_register_ip_addresses, (void *)card,SIGCHLD); | 1054 | kernel_thread(qeth_register_ip_addresses, (void *)card,SIGCHLD); |
1055 | if (qeth_do_start_thread(card, QETH_SET_PROMISC_MODE_THREAD)) | ||
1056 | kernel_thread(qeth_set_promisc_mode, (void *)card, SIGCHLD); | ||
1008 | if (qeth_do_start_thread(card, QETH_RECOVER_THREAD)) | 1057 | if (qeth_do_start_thread(card, QETH_RECOVER_THREAD)) |
1009 | kernel_thread(qeth_recover, (void *) card, SIGCHLD); | 1058 | kernel_thread(qeth_recover, (void *) card, SIGCHLD); |
1010 | } | 1059 | } |
@@ -1661,7 +1710,6 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) | |||
1661 | "IP address reset.\n", | 1710 | "IP address reset.\n", |
1662 | QETH_CARD_IFNAME(card), | 1711 | QETH_CARD_IFNAME(card), |
1663 | card->info.chpid); | 1712 | card->info.chpid); |
1664 | netif_carrier_on(card->dev); | ||
1665 | qeth_schedule_recovery(card); | 1713 | qeth_schedule_recovery(card); |
1666 | return NULL; | 1714 | return NULL; |
1667 | case IPA_CMD_MODCCID: | 1715 | case IPA_CMD_MODCCID: |
@@ -1910,7 +1958,7 @@ qeth_osn_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, | |||
1910 | { | 1958 | { |
1911 | u16 s1, s2; | 1959 | u16 s1, s2; |
1912 | 1960 | ||
1913 | QETH_DBF_TEXT(trace,4,"osndipa"); | 1961 | QETH_DBF_TEXT(trace,4,"osndipa"); |
1914 | 1962 | ||
1915 | qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2); | 1963 | qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2); |
1916 | s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len); | 1964 | s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len); |
@@ -2154,24 +2202,21 @@ qeth_ulp_setup(struct qeth_card *card) | |||
2154 | } | 2202 | } |
2155 | 2203 | ||
2156 | static inline int | 2204 | static inline int |
2157 | qeth_check_for_inbound_error(struct qeth_qdio_buffer *buf, | 2205 | qeth_check_qdio_errors(struct qdio_buffer *buf, unsigned int qdio_error, |
2158 | unsigned int qdio_error, | 2206 | unsigned int siga_error, const char *dbftext) |
2159 | unsigned int siga_error) | ||
2160 | { | 2207 | { |
2161 | int rc = 0; | ||
2162 | |||
2163 | if (qdio_error || siga_error) { | 2208 | if (qdio_error || siga_error) { |
2164 | QETH_DBF_TEXT(trace, 2, "qdinerr"); | 2209 | QETH_DBF_TEXT(trace, 2, dbftext); |
2165 | QETH_DBF_TEXT(qerr, 2, "qdinerr"); | 2210 | QETH_DBF_TEXT(qerr, 2, dbftext); |
2166 | QETH_DBF_TEXT_(qerr, 2, " F15=%02X", | 2211 | QETH_DBF_TEXT_(qerr, 2, " F15=%02X", |
2167 | buf->buffer->element[15].flags & 0xff); | 2212 | buf->element[15].flags & 0xff); |
2168 | QETH_DBF_TEXT_(qerr, 2, " F14=%02X", | 2213 | QETH_DBF_TEXT_(qerr, 2, " F14=%02X", |
2169 | buf->buffer->element[14].flags & 0xff); | 2214 | buf->element[14].flags & 0xff); |
2170 | QETH_DBF_TEXT_(qerr, 2, " qerr=%X", qdio_error); | 2215 | QETH_DBF_TEXT_(qerr, 2, " qerr=%X", qdio_error); |
2171 | QETH_DBF_TEXT_(qerr, 2, " serr=%X", siga_error); | 2216 | QETH_DBF_TEXT_(qerr, 2, " serr=%X", siga_error); |
2172 | rc = 1; | 2217 | return 1; |
2173 | } | 2218 | } |
2174 | return rc; | 2219 | return 0; |
2175 | } | 2220 | } |
2176 | 2221 | ||
2177 | static inline struct sk_buff * | 2222 | static inline struct sk_buff * |
@@ -2720,8 +2765,9 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status, | |||
2720 | for (i = first_element; i < (first_element + count); ++i) { | 2765 | for (i = first_element; i < (first_element + count); ++i) { |
2721 | index = i % QDIO_MAX_BUFFERS_PER_Q; | 2766 | index = i % QDIO_MAX_BUFFERS_PER_Q; |
2722 | buffer = &card->qdio.in_q->bufs[index]; | 2767 | buffer = &card->qdio.in_q->bufs[index]; |
2723 | if (!((status == QDIO_STATUS_LOOK_FOR_ERROR) && | 2768 | if (!((status & QDIO_STATUS_LOOK_FOR_ERROR) && |
2724 | qeth_check_for_inbound_error(buffer, qdio_err, siga_err))) | 2769 | qeth_check_qdio_errors(buffer->buffer, |
2770 | qdio_err, siga_err,"qinerr"))) | ||
2725 | qeth_process_inbound_buffer(card, buffer, index); | 2771 | qeth_process_inbound_buffer(card, buffer, index); |
2726 | /* clear buffer and give back to hardware */ | 2772 | /* clear buffer and give back to hardware */ |
2727 | qeth_put_buffer_pool_entry(card, buffer->pool_entry); | 2773 | qeth_put_buffer_pool_entry(card, buffer->pool_entry); |
@@ -2736,12 +2782,13 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status, | |||
2736 | static inline int | 2782 | static inline int |
2737 | qeth_handle_send_error(struct qeth_card *card, | 2783 | qeth_handle_send_error(struct qeth_card *card, |
2738 | struct qeth_qdio_out_buffer *buffer, | 2784 | struct qeth_qdio_out_buffer *buffer, |
2739 | int qdio_err, int siga_err) | 2785 | unsigned int qdio_err, unsigned int siga_err) |
2740 | { | 2786 | { |
2741 | int sbalf15 = buffer->buffer->element[15].flags & 0xff; | 2787 | int sbalf15 = buffer->buffer->element[15].flags & 0xff; |
2742 | int cc = siga_err & 3; | 2788 | int cc = siga_err & 3; |
2743 | 2789 | ||
2744 | QETH_DBF_TEXT(trace, 6, "hdsnderr"); | 2790 | QETH_DBF_TEXT(trace, 6, "hdsnderr"); |
2791 | qeth_check_qdio_errors(buffer->buffer, qdio_err, siga_err, "qouterr"); | ||
2745 | switch (cc) { | 2792 | switch (cc) { |
2746 | case 0: | 2793 | case 0: |
2747 | if (qdio_err){ | 2794 | if (qdio_err){ |
@@ -2998,7 +3045,8 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status, | |||
2998 | for(i = first_element; i < (first_element + count); ++i){ | 3045 | for(i = first_element; i < (first_element + count); ++i){ |
2999 | buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; | 3046 | buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; |
3000 | /*we only handle the KICK_IT error by doing a recovery */ | 3047 | /*we only handle the KICK_IT error by doing a recovery */ |
3001 | if (qeth_handle_send_error(card, buffer, qdio_error, siga_error) | 3048 | if (qeth_handle_send_error(card, buffer, |
3049 | qdio_error, siga_error) | ||
3002 | == QETH_SEND_ERROR_KICK_IT){ | 3050 | == QETH_SEND_ERROR_KICK_IT){ |
3003 | netif_stop_queue(card->dev); | 3051 | netif_stop_queue(card->dev); |
3004 | qeth_schedule_recovery(card); | 3052 | qeth_schedule_recovery(card); |
@@ -3240,7 +3288,6 @@ qeth_init_qdio_info(struct qeth_card *card) | |||
3240 | card->qdio.in_buf_pool.buf_count = card->qdio.init_pool.buf_count; | 3288 | card->qdio.in_buf_pool.buf_count = card->qdio.init_pool.buf_count; |
3241 | INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list); | 3289 | INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list); |
3242 | INIT_LIST_HEAD(&card->qdio.init_pool.entry_list); | 3290 | INIT_LIST_HEAD(&card->qdio.init_pool.entry_list); |
3243 | /* outbound */ | ||
3244 | } | 3291 | } |
3245 | 3292 | ||
3246 | static int | 3293 | static int |
@@ -3682,6 +3729,9 @@ qeth_verify_vlan_dev(struct net_device *dev, struct qeth_card *card) | |||
3682 | break; | 3729 | break; |
3683 | } | 3730 | } |
3684 | } | 3731 | } |
3732 | if (rc && !(VLAN_DEV_INFO(dev)->real_dev->priv == (void *)card)) | ||
3733 | return 0; | ||
3734 | |||
3685 | #endif | 3735 | #endif |
3686 | return rc; | 3736 | return rc; |
3687 | } | 3737 | } |
@@ -3749,7 +3799,7 @@ qeth_open(struct net_device *dev) | |||
3749 | 3799 | ||
3750 | if ( (card->info.type != QETH_CARD_TYPE_OSN) && | 3800 | if ( (card->info.type != QETH_CARD_TYPE_OSN) && |
3751 | (card->options.layer2) && | 3801 | (card->options.layer2) && |
3752 | (!card->info.layer2_mac_registered)) { | 3802 | (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) { |
3753 | QETH_DBF_TEXT(trace,4,"nomacadr"); | 3803 | QETH_DBF_TEXT(trace,4,"nomacadr"); |
3754 | return -EPERM; | 3804 | return -EPERM; |
3755 | } | 3805 | } |
@@ -3758,10 +3808,8 @@ qeth_open(struct net_device *dev) | |||
3758 | card->data.state = CH_STATE_UP; | 3808 | card->data.state = CH_STATE_UP; |
3759 | card->state = CARD_STATE_UP; | 3809 | card->state = CARD_STATE_UP; |
3760 | 3810 | ||
3761 | if (!card->lan_online){ | 3811 | if (!card->lan_online && netif_carrier_ok(dev)) |
3762 | if (netif_carrier_ok(dev)) | 3812 | netif_carrier_off(dev); |
3763 | netif_carrier_off(dev); | ||
3764 | } | ||
3765 | return 0; | 3813 | return 0; |
3766 | } | 3814 | } |
3767 | 3815 | ||
@@ -4311,6 +4359,8 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, | |||
4311 | out: | 4359 | out: |
4312 | if (flush_count) | 4360 | if (flush_count) |
4313 | qeth_flush_buffers(queue, 0, start_index, flush_count); | 4361 | qeth_flush_buffers(queue, 0, start_index, flush_count); |
4362 | else if (!atomic_read(&queue->set_pci_flags_count)) | ||
4363 | atomic_swap(&queue->state, QETH_OUT_Q_LOCKED_FLUSH); | ||
4314 | /* | 4364 | /* |
4315 | * queue->state will go from LOCKED -> UNLOCKED or from | 4365 | * queue->state will go from LOCKED -> UNLOCKED or from |
4316 | * LOCKED_FLUSH -> LOCKED if output_handler wanted to 'notify' us | 4366 | * LOCKED_FLUSH -> LOCKED if output_handler wanted to 'notify' us |
@@ -4975,6 +5025,10 @@ qeth_default_setassparms_cb(struct qeth_card *, struct qeth_reply *, | |||
4975 | unsigned long); | 5025 | unsigned long); |
4976 | 5026 | ||
4977 | static int | 5027 | static int |
5028 | qeth_default_setadapterparms_cb(struct qeth_card *card, | ||
5029 | struct qeth_reply *reply, | ||
5030 | unsigned long data); | ||
5031 | static int | ||
4978 | qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *, | 5032 | qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *, |
4979 | __u16, long, | 5033 | __u16, long, |
4980 | int (*reply_cb) | 5034 | int (*reply_cb) |
@@ -5301,8 +5355,7 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid) | |||
5301 | struct qeth_ipaddr *addr; | 5355 | struct qeth_ipaddr *addr; |
5302 | 5356 | ||
5303 | QETH_DBF_TEXT(trace, 4, "frvaddr4"); | 5357 | QETH_DBF_TEXT(trace, 4, "frvaddr4"); |
5304 | if (!card->vlangrp) | 5358 | |
5305 | return; | ||
5306 | rcu_read_lock(); | 5359 | rcu_read_lock(); |
5307 | in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]); | 5360 | in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]); |
5308 | if (!in_dev) | 5361 | if (!in_dev) |
@@ -5330,8 +5383,7 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid) | |||
5330 | struct qeth_ipaddr *addr; | 5383 | struct qeth_ipaddr *addr; |
5331 | 5384 | ||
5332 | QETH_DBF_TEXT(trace, 4, "frvaddr6"); | 5385 | QETH_DBF_TEXT(trace, 4, "frvaddr6"); |
5333 | if (!card->vlangrp) | 5386 | |
5334 | return; | ||
5335 | in6_dev = in6_dev_get(card->vlangrp->vlan_devices[vid]); | 5387 | in6_dev = in6_dev_get(card->vlangrp->vlan_devices[vid]); |
5336 | if (!in6_dev) | 5388 | if (!in6_dev) |
5337 | return; | 5389 | return; |
@@ -5351,10 +5403,38 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid) | |||
5351 | } | 5403 | } |
5352 | 5404 | ||
5353 | static void | 5405 | static void |
5406 | qeth_free_vlan_addresses(struct qeth_card *card, unsigned short vid) | ||
5407 | { | ||
5408 | if (card->options.layer2 || !card->vlangrp) | ||
5409 | return; | ||
5410 | qeth_free_vlan_addresses4(card, vid); | ||
5411 | qeth_free_vlan_addresses6(card, vid); | ||
5412 | } | ||
5413 | |||
5414 | static int | ||
5415 | qeth_layer2_send_setdelvlan_cb(struct qeth_card *card, | ||
5416 | struct qeth_reply *reply, | ||
5417 | unsigned long data) | ||
5418 | { | ||
5419 | struct qeth_ipa_cmd *cmd; | ||
5420 | |||
5421 | QETH_DBF_TEXT(trace, 2, "L2sdvcb"); | ||
5422 | cmd = (struct qeth_ipa_cmd *) data; | ||
5423 | if (cmd->hdr.return_code) { | ||
5424 | PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. " | ||
5425 | "Continuing\n",cmd->data.setdelvlan.vlan_id, | ||
5426 | QETH_CARD_IFNAME(card), cmd->hdr.return_code); | ||
5427 | QETH_DBF_TEXT_(trace, 2, "L2VL%4x", cmd->hdr.command); | ||
5428 | QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card)); | ||
5429 | QETH_DBF_TEXT_(trace, 2, "err%d", cmd->hdr.return_code); | ||
5430 | } | ||
5431 | return 0; | ||
5432 | } | ||
5433 | |||
5434 | static int | ||
5354 | qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i, | 5435 | qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i, |
5355 | enum qeth_ipa_cmds ipacmd) | 5436 | enum qeth_ipa_cmds ipacmd) |
5356 | { | 5437 | { |
5357 | int rc; | ||
5358 | struct qeth_ipa_cmd *cmd; | 5438 | struct qeth_ipa_cmd *cmd; |
5359 | struct qeth_cmd_buffer *iob; | 5439 | struct qeth_cmd_buffer *iob; |
5360 | 5440 | ||
@@ -5362,15 +5442,8 @@ qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i, | |||
5362 | iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4); | 5442 | iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4); |
5363 | cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); | 5443 | cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); |
5364 | cmd->data.setdelvlan.vlan_id = i; | 5444 | cmd->data.setdelvlan.vlan_id = i; |
5365 | 5445 | return qeth_send_ipa_cmd(card, iob, | |
5366 | rc = qeth_send_ipa_cmd(card, iob, NULL, NULL); | 5446 | qeth_layer2_send_setdelvlan_cb, NULL); |
5367 | if (rc) { | ||
5368 | PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. " | ||
5369 | "Continuing\n",i, QETH_CARD_IFNAME(card), rc); | ||
5370 | QETH_DBF_TEXT_(trace, 2, "L2VL%4x", ipacmd); | ||
5371 | QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card)); | ||
5372 | QETH_DBF_TEXT_(trace, 2, "err%d", rc); | ||
5373 | } | ||
5374 | } | 5447 | } |
5375 | 5448 | ||
5376 | static void | 5449 | static void |
@@ -5420,8 +5493,7 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | |||
5420 | qeth_free_vlan_skbs(card, vid); | 5493 | qeth_free_vlan_skbs(card, vid); |
5421 | spin_lock_irqsave(&card->vlanlock, flags); | 5494 | spin_lock_irqsave(&card->vlanlock, flags); |
5422 | /* unregister IP addresses of vlan device */ | 5495 | /* unregister IP addresses of vlan device */ |
5423 | qeth_free_vlan_addresses4(card, vid); | 5496 | qeth_free_vlan_addresses(card, vid); |
5424 | qeth_free_vlan_addresses6(card, vid); | ||
5425 | if (card->vlangrp) | 5497 | if (card->vlangrp) |
5426 | card->vlangrp->vlan_devices[vid] = NULL; | 5498 | card->vlangrp->vlan_devices[vid] = NULL; |
5427 | spin_unlock_irqrestore(&card->vlanlock, flags); | 5499 | spin_unlock_irqrestore(&card->vlanlock, flags); |
@@ -5430,6 +5502,59 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | |||
5430 | qeth_set_multicast_list(card->dev); | 5502 | qeth_set_multicast_list(card->dev); |
5431 | } | 5503 | } |
5432 | #endif | 5504 | #endif |
5505 | /** | ||
5506 | * Examine hardware response to SET_PROMISC_MODE | ||
5507 | */ | ||
5508 | static int | ||
5509 | qeth_setadp_promisc_mode_cb(struct qeth_card *card, | ||
5510 | struct qeth_reply *reply, | ||
5511 | unsigned long data) | ||
5512 | { | ||
5513 | struct qeth_ipa_cmd *cmd; | ||
5514 | struct qeth_ipacmd_setadpparms *setparms; | ||
5515 | |||
5516 | QETH_DBF_TEXT(trace,4,"prmadpcb"); | ||
5517 | |||
5518 | cmd = (struct qeth_ipa_cmd *) data; | ||
5519 | setparms = &(cmd->data.setadapterparms); | ||
5520 | |||
5521 | qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd); | ||
5522 | if (cmd->hdr.return_code) { | ||
5523 | QETH_DBF_TEXT_(trace,4,"prmrc%2.2x",cmd->hdr.return_code); | ||
5524 | setparms->data.mode = SET_PROMISC_MODE_OFF; | ||
5525 | } | ||
5526 | card->info.promisc_mode = setparms->data.mode; | ||
5527 | return 0; | ||
5528 | } | ||
5529 | /* | ||
5530 | * Set promiscuous mode (on or off) (SET_PROMISC_MODE command) | ||
5531 | */ | ||
5532 | static void | ||
5533 | qeth_setadp_promisc_mode(struct qeth_card *card) | ||
5534 | { | ||
5535 | enum qeth_ipa_promisc_modes mode; | ||
5536 | struct net_device *dev = card->dev; | ||
5537 | struct qeth_cmd_buffer *iob; | ||
5538 | struct qeth_ipa_cmd *cmd; | ||
5539 | |||
5540 | QETH_DBF_TEXT(trace, 4, "setprom"); | ||
5541 | |||
5542 | if (((dev->flags & IFF_PROMISC) && | ||
5543 | (card->info.promisc_mode == SET_PROMISC_MODE_ON)) || | ||
5544 | (!(dev->flags & IFF_PROMISC) && | ||
5545 | (card->info.promisc_mode == SET_PROMISC_MODE_OFF))) | ||
5546 | return; | ||
5547 | mode = SET_PROMISC_MODE_OFF; | ||
5548 | if (dev->flags & IFF_PROMISC) | ||
5549 | mode = SET_PROMISC_MODE_ON; | ||
5550 | QETH_DBF_TEXT_(trace, 4, "mode:%x", mode); | ||
5551 | |||
5552 | iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_PROMISC_MODE, | ||
5553 | sizeof(struct qeth_ipacmd_setadpparms)); | ||
5554 | cmd = (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE); | ||
5555 | cmd->data.setadapterparms.data.mode = mode; | ||
5556 | qeth_send_ipa_cmd(card, iob, qeth_setadp_promisc_mode_cb, NULL); | ||
5557 | } | ||
5433 | 5558 | ||
5434 | /** | 5559 | /** |
5435 | * set multicast address on card | 5560 | * set multicast address on card |
@@ -5444,12 +5569,22 @@ qeth_set_multicast_list(struct net_device *dev) | |||
5444 | 5569 | ||
5445 | QETH_DBF_TEXT(trace,3,"setmulti"); | 5570 | QETH_DBF_TEXT(trace,3,"setmulti"); |
5446 | qeth_delete_mc_addresses(card); | 5571 | qeth_delete_mc_addresses(card); |
5572 | if (card->options.layer2) { | ||
5573 | qeth_layer2_add_multicast(card); | ||
5574 | goto out; | ||
5575 | } | ||
5447 | qeth_add_multicast_ipv4(card); | 5576 | qeth_add_multicast_ipv4(card); |
5448 | #ifdef CONFIG_QETH_IPV6 | 5577 | #ifdef CONFIG_QETH_IPV6 |
5449 | qeth_add_multicast_ipv6(card); | 5578 | qeth_add_multicast_ipv6(card); |
5450 | #endif | 5579 | #endif |
5580 | out: | ||
5451 | if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) | 5581 | if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) |
5452 | schedule_work(&card->kernel_thread_starter); | 5582 | schedule_work(&card->kernel_thread_starter); |
5583 | if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE)) | ||
5584 | return; | ||
5585 | if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0) | ||
5586 | schedule_work(&card->kernel_thread_starter); | ||
5587 | |||
5453 | } | 5588 | } |
5454 | 5589 | ||
5455 | static int | 5590 | static int |
@@ -5657,6 +5792,24 @@ qeth_add_multicast_ipv4(struct qeth_card *card) | |||
5657 | in_dev_put(in4_dev); | 5792 | in_dev_put(in4_dev); |
5658 | } | 5793 | } |
5659 | 5794 | ||
5795 | static void | ||
5796 | qeth_layer2_add_multicast(struct qeth_card *card) | ||
5797 | { | ||
5798 | struct qeth_ipaddr *ipm; | ||
5799 | struct dev_mc_list *dm; | ||
5800 | |||
5801 | QETH_DBF_TEXT(trace,4,"L2addmc"); | ||
5802 | for (dm = card->dev->mc_list; dm; dm = dm->next) { | ||
5803 | ipm = qeth_get_addr_buffer(QETH_PROT_IPV4); | ||
5804 | if (!ipm) | ||
5805 | continue; | ||
5806 | memcpy(ipm->mac,dm->dmi_addr,MAX_ADDR_LEN); | ||
5807 | ipm->is_multicast = 1; | ||
5808 | if (!qeth_add_ip(card, ipm)) | ||
5809 | kfree(ipm); | ||
5810 | } | ||
5811 | } | ||
5812 | |||
5660 | #ifdef CONFIG_QETH_IPV6 | 5813 | #ifdef CONFIG_QETH_IPV6 |
5661 | static inline void | 5814 | static inline void |
5662 | qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev) | 5815 | qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev) |
@@ -5716,10 +5869,8 @@ qeth_add_multicast_ipv6(struct qeth_card *card) | |||
5716 | struct inet6_dev *in6_dev; | 5869 | struct inet6_dev *in6_dev; |
5717 | 5870 | ||
5718 | QETH_DBF_TEXT(trace,4,"chkmcv6"); | 5871 | QETH_DBF_TEXT(trace,4,"chkmcv6"); |
5719 | if ((card->options.layer2 == 0) && | 5872 | if (!qeth_is_supported(card, IPA_IPV6)) |
5720 | (!qeth_is_supported(card, IPA_IPV6)) ) | ||
5721 | return ; | 5873 | return ; |
5722 | |||
5723 | in6_dev = in6_dev_get(card->dev); | 5874 | in6_dev = in6_dev_get(card->dev); |
5724 | if (in6_dev == NULL) | 5875 | if (in6_dev == NULL) |
5725 | return; | 5876 | return; |
@@ -5825,10 +5976,10 @@ qeth_layer2_send_setmac_cb(struct qeth_card *card, | |||
5825 | PRINT_WARN("Error in registering MAC address on " \ | 5976 | PRINT_WARN("Error in registering MAC address on " \ |
5826 | "device %s: x%x\n", CARD_BUS_ID(card), | 5977 | "device %s: x%x\n", CARD_BUS_ID(card), |
5827 | cmd->hdr.return_code); | 5978 | cmd->hdr.return_code); |
5828 | card->info.layer2_mac_registered = 0; | 5979 | card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; |
5829 | cmd->hdr.return_code = -EIO; | 5980 | cmd->hdr.return_code = -EIO; |
5830 | } else { | 5981 | } else { |
5831 | card->info.layer2_mac_registered = 1; | 5982 | card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED; |
5832 | memcpy(card->dev->dev_addr,cmd->data.setdelmac.mac, | 5983 | memcpy(card->dev->dev_addr,cmd->data.setdelmac.mac, |
5833 | OSA_ADDR_LEN); | 5984 | OSA_ADDR_LEN); |
5834 | PRINT_INFO("MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " | 5985 | PRINT_INFO("MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " |
@@ -5866,7 +6017,7 @@ qeth_layer2_send_delmac_cb(struct qeth_card *card, | |||
5866 | cmd->hdr.return_code = -EIO; | 6017 | cmd->hdr.return_code = -EIO; |
5867 | return 0; | 6018 | return 0; |
5868 | } | 6019 | } |
5869 | card->info.layer2_mac_registered = 0; | 6020 | card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; |
5870 | 6021 | ||
5871 | return 0; | 6022 | return 0; |
5872 | } | 6023 | } |
@@ -5874,7 +6025,7 @@ static int | |||
5874 | qeth_layer2_send_delmac(struct qeth_card *card, __u8 *mac) | 6025 | qeth_layer2_send_delmac(struct qeth_card *card, __u8 *mac) |
5875 | { | 6026 | { |
5876 | QETH_DBF_TEXT(trace, 2, "L2Delmac"); | 6027 | QETH_DBF_TEXT(trace, 2, "L2Delmac"); |
5877 | if (!card->info.layer2_mac_registered) | 6028 | if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)) |
5878 | return 0; | 6029 | return 0; |
5879 | return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_DELVMAC, | 6030 | return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_DELVMAC, |
5880 | qeth_layer2_send_delmac_cb); | 6031 | qeth_layer2_send_delmac_cb); |
@@ -5896,7 +6047,7 @@ qeth_layer2_set_mac_address(struct net_device *dev, void *p) | |||
5896 | card = (struct qeth_card *) dev->priv; | 6047 | card = (struct qeth_card *) dev->priv; |
5897 | 6048 | ||
5898 | if (!card->options.layer2) { | 6049 | if (!card->options.layer2) { |
5899 | PRINT_WARN("Setting MAC address on %s is not supported" | 6050 | PRINT_WARN("Setting MAC address on %s is not supported " |
5900 | "in Layer 3 mode.\n", dev->name); | 6051 | "in Layer 3 mode.\n", dev->name); |
5901 | QETH_DBF_TEXT(trace, 3, "setmcLY3"); | 6052 | QETH_DBF_TEXT(trace, 3, "setmcLY3"); |
5902 | return -EOPNOTSUPP; | 6053 | return -EOPNOTSUPP; |
@@ -6441,6 +6592,8 @@ qeth_default_setadapterparms_cb(struct qeth_card *card, | |||
6441 | return 0; | 6592 | return 0; |
6442 | } | 6593 | } |
6443 | 6594 | ||
6595 | |||
6596 | |||
6444 | static int | 6597 | static int |
6445 | qeth_query_setadapterparms_cb(struct qeth_card *card, struct qeth_reply *reply, | 6598 | qeth_query_setadapterparms_cb(struct qeth_card *card, struct qeth_reply *reply, |
6446 | unsigned long data) | 6599 | unsigned long data) |
@@ -6481,8 +6634,13 @@ qeth_setadpparms_change_macaddr_cb(struct qeth_card *card, | |||
6481 | QETH_DBF_TEXT(trace,4,"chgmaccb"); | 6634 | QETH_DBF_TEXT(trace,4,"chgmaccb"); |
6482 | 6635 | ||
6483 | cmd = (struct qeth_ipa_cmd *) data; | 6636 | cmd = (struct qeth_ipa_cmd *) data; |
6484 | memcpy(card->dev->dev_addr, | 6637 | if (!card->options.layer2 || card->info.guestlan || |
6485 | &cmd->data.setadapterparms.data.change_addr.addr,OSA_ADDR_LEN); | 6638 | !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) { |
6639 | memcpy(card->dev->dev_addr, | ||
6640 | &cmd->data.setadapterparms.data.change_addr.addr, | ||
6641 | OSA_ADDR_LEN); | ||
6642 | card->info.mac_bits |= QETH_LAYER2_MAC_READ; | ||
6643 | } | ||
6486 | qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd); | 6644 | qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd); |
6487 | return 0; | 6645 | return 0; |
6488 | } | 6646 | } |
@@ -6602,6 +6760,12 @@ qeth_layer2_initialize(struct qeth_card *card) | |||
6602 | QETH_DBF_TEXT(setup, 2, "doL2init"); | 6760 | QETH_DBF_TEXT(setup, 2, "doL2init"); |
6603 | QETH_DBF_TEXT_(setup, 2, "doL2%s", CARD_BUS_ID(card)); | 6761 | QETH_DBF_TEXT_(setup, 2, "doL2%s", CARD_BUS_ID(card)); |
6604 | 6762 | ||
6763 | rc = qeth_query_setadapterparms(card); | ||
6764 | if (rc) { | ||
6765 | PRINT_WARN("could not query adapter parameters on device %s: " | ||
6766 | "x%x\n", CARD_BUS_ID(card), rc); | ||
6767 | } | ||
6768 | |||
6605 | rc = qeth_setadpparms_change_macaddr(card); | 6769 | rc = qeth_setadpparms_change_macaddr(card); |
6606 | if (rc) { | 6770 | if (rc) { |
6607 | PRINT_WARN("couldn't get MAC address on " | 6771 | PRINT_WARN("couldn't get MAC address on " |
@@ -7769,8 +7933,8 @@ __qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
7769 | QETH_DBF_TEXT_(setup, 2, "6err%d", rc); | 7933 | QETH_DBF_TEXT_(setup, 2, "6err%d", rc); |
7770 | goto out_remove; | 7934 | goto out_remove; |
7771 | } | 7935 | } |
7772 | /*maybe it was set offline without ifconfig down | 7936 | netif_carrier_on(card->dev); |
7773 | * we can also use this state for recovery purposes*/ | 7937 | |
7774 | qeth_set_allowed_threads(card, 0xffffffff, 0); | 7938 | qeth_set_allowed_threads(card, 0xffffffff, 0); |
7775 | if (recover_flag == CARD_STATE_RECOVER) | 7939 | if (recover_flag == CARD_STATE_RECOVER) |
7776 | qeth_start_again(card, recovery_mode); | 7940 | qeth_start_again(card, recovery_mode); |
@@ -8548,7 +8712,7 @@ EXPORT_SYMBOL(qeth_osn_deregister); | |||
8548 | EXPORT_SYMBOL(qeth_osn_assist); | 8712 | EXPORT_SYMBOL(qeth_osn_assist); |
8549 | module_init(qeth_init); | 8713 | module_init(qeth_init); |
8550 | module_exit(qeth_exit); | 8714 | module_exit(qeth_exit); |
8551 | MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>"); | 8715 | MODULE_AUTHOR("Frank Pavlic <fpavlic@de.ibm.com>"); |
8552 | MODULE_DESCRIPTION("Linux on zSeries OSA Express and HiperSockets support\n" \ | 8716 | MODULE_DESCRIPTION("Linux on zSeries OSA Express and HiperSockets support\n" \ |
8553 | "Copyright 2000,2003 IBM Corporation\n"); | 8717 | "Copyright 2000,2003 IBM Corporation\n"); |
8554 | 8718 | ||
diff --git a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c index 30e053d3cac2..5f8754addc14 100644 --- a/drivers/s390/net/qeth_mpc.c +++ b/drivers/s390/net/qeth_mpc.c | |||
@@ -4,14 +4,14 @@ | |||
4 | * Linux on zSeries OSA Express and HiperSockets support | 4 | * Linux on zSeries OSA Express and HiperSockets support |
5 | * | 5 | * |
6 | * Copyright 2000,2003 IBM Corporation | 6 | * Copyright 2000,2003 IBM Corporation |
7 | * Author(s): Frank Pavlic <pavlic@de.ibm.com> | 7 | * Author(s): Frank Pavlic <fpavlic@de.ibm.com> |
8 | * Thomas Spatzier <tspat@de.ibm.com> | 8 | * Thomas Spatzier <tspat@de.ibm.com> |
9 | * | 9 | * |
10 | */ | 10 | */ |
11 | #include <asm/cio.h> | 11 | #include <asm/cio.h> |
12 | #include "qeth_mpc.h" | 12 | #include "qeth_mpc.h" |
13 | 13 | ||
14 | const char *VERSION_QETH_MPC_C = "$Revision: 1.12 $"; | 14 | const char *VERSION_QETH_MPC_C = "$Revision: 1.13 $"; |
15 | 15 | ||
16 | unsigned char IDX_ACTIVATE_READ[]={ | 16 | unsigned char IDX_ACTIVATE_READ[]={ |
17 | 0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00, | 17 | 0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00, |
diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h index 7edc5f1fc0d2..864cec5f6c62 100644 --- a/drivers/s390/net/qeth_mpc.h +++ b/drivers/s390/net/qeth_mpc.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * Copyright 2000,2003 IBM Corporation | 6 | * Copyright 2000,2003 IBM Corporation |
7 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com> | 7 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com> |
8 | * Thomas Spatzier <tspat@de.ibm.com> | 8 | * Thomas Spatzier <tspat@de.ibm.com> |
9 | * Frank Pavlic <pavlic@de.ibm.com> | 9 | * Frank Pavlic <fpavlic@de.ibm.com> |
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | #ifndef __QETH_MPC_H__ | 12 | #ifndef __QETH_MPC_H__ |
@@ -14,14 +14,14 @@ | |||
14 | 14 | ||
15 | #include <asm/qeth.h> | 15 | #include <asm/qeth.h> |
16 | 16 | ||
17 | #define VERSION_QETH_MPC_H "$Revision: 1.43 $" | 17 | #define VERSION_QETH_MPC_H "$Revision: 1.46 $" |
18 | 18 | ||
19 | extern const char *VERSION_QETH_MPC_C; | 19 | extern const char *VERSION_QETH_MPC_C; |
20 | 20 | ||
21 | #define IPA_PDU_HEADER_SIZE 0x40 | 21 | #define IPA_PDU_HEADER_SIZE 0x40 |
22 | #define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer+0x0e) | 22 | #define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer+0x0e) |
23 | #define QETH_IPA_PDU_LEN_PDU1(buffer) (buffer+0x26) | 23 | #define QETH_IPA_PDU_LEN_PDU1(buffer) (buffer+0x26) |
24 | #define QETH_IPA_PDU_LEN_PDU2(buffer) (buffer+0x2a) | 24 | #define QETH_IPA_PDU_LEN_PDU2(buffer) (buffer+0x29) |
25 | #define QETH_IPA_PDU_LEN_PDU3(buffer) (buffer+0x3a) | 25 | #define QETH_IPA_PDU_LEN_PDU3(buffer) (buffer+0x3a) |
26 | 26 | ||
27 | extern unsigned char IPA_PDU_HEADER[]; | 27 | extern unsigned char IPA_PDU_HEADER[]; |
@@ -217,7 +217,7 @@ enum qeth_ipa_setadp_cmd { | |||
217 | IPA_SETADP_SEND_OSA_MESSAGE = 0x0100, | 217 | IPA_SETADP_SEND_OSA_MESSAGE = 0x0100, |
218 | IPA_SETADP_SET_SNMP_CONTROL = 0x0200, | 218 | IPA_SETADP_SET_SNMP_CONTROL = 0x0200, |
219 | IPA_SETADP_READ_SNMP_PARMS = 0x0400, | 219 | IPA_SETADP_READ_SNMP_PARMS = 0x0400, |
220 | IPA_SETADP_WRITE_SNMP_PARMS = 0x0800, | 220 | IPA_SETADP_SET_PROMISC_MODE = 0x0800, |
221 | IPA_SETADP_QUERY_CARD_INFO = 0x1000, | 221 | IPA_SETADP_QUERY_CARD_INFO = 0x1000, |
222 | }; | 222 | }; |
223 | enum qeth_ipa_mac_ops { | 223 | enum qeth_ipa_mac_ops { |
@@ -232,9 +232,12 @@ enum qeth_ipa_addr_ops { | |||
232 | CHANGE_ADDR_ADD_ADDR = 1, | 232 | CHANGE_ADDR_ADD_ADDR = 1, |
233 | CHANGE_ADDR_DEL_ADDR = 2, | 233 | CHANGE_ADDR_DEL_ADDR = 2, |
234 | CHANGE_ADDR_FLUSH_ADDR_TABLE = 4, | 234 | CHANGE_ADDR_FLUSH_ADDR_TABLE = 4, |
235 | |||
236 | |||
237 | }; | 235 | }; |
236 | enum qeth_ipa_promisc_modes { | ||
237 | SET_PROMISC_MODE_OFF = 0, | ||
238 | SET_PROMISC_MODE_ON = 1, | ||
239 | }; | ||
240 | |||
238 | /* (SET)DELIP(M) IPA stuff ***************************************************/ | 241 | /* (SET)DELIP(M) IPA stuff ***************************************************/ |
239 | struct qeth_ipacmd_setdelip4 { | 242 | struct qeth_ipacmd_setdelip4 { |
240 | __u8 ip_addr[4]; | 243 | __u8 ip_addr[4]; |
diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c index f2ccfea8fdb8..7bf35098831e 100644 --- a/drivers/s390/net/qeth_proc.c +++ b/drivers/s390/net/qeth_proc.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * | 2 | * |
3 | * linux/drivers/s390/net/qeth_fs.c ($Revision: 1.13 $) | 3 | * linux/drivers/s390/net/qeth_fs.c ($Revision: 1.16 $) |
4 | * | 4 | * |
5 | * Linux on zSeries OSA Express and HiperSockets support | 5 | * Linux on zSeries OSA Express and HiperSockets support |
6 | * This file contains code related to procfs. | 6 | * This file contains code related to procfs. |
@@ -21,7 +21,7 @@ | |||
21 | #include "qeth_mpc.h" | 21 | #include "qeth_mpc.h" |
22 | #include "qeth_fs.h" | 22 | #include "qeth_fs.h" |
23 | 23 | ||
24 | const char *VERSION_QETH_PROC_C = "$Revision: 1.13 $"; | 24 | const char *VERSION_QETH_PROC_C = "$Revision: 1.16 $"; |
25 | 25 | ||
26 | /***** /proc/qeth *****/ | 26 | /***** /proc/qeth *****/ |
27 | #define QETH_PROCFILE_NAME "qeth" | 27 | #define QETH_PROCFILE_NAME "qeth" |
@@ -30,30 +30,26 @@ static struct proc_dir_entry *qeth_procfile; | |||
30 | static int | 30 | static int |
31 | qeth_procfile_seq_match(struct device *dev, void *data) | 31 | qeth_procfile_seq_match(struct device *dev, void *data) |
32 | { | 32 | { |
33 | return 1; | 33 | return(dev ? 1 : 0); |
34 | } | 34 | } |
35 | 35 | ||
36 | static void * | 36 | static void * |
37 | qeth_procfile_seq_start(struct seq_file *s, loff_t *offset) | 37 | qeth_procfile_seq_start(struct seq_file *s, loff_t *offset) |
38 | { | 38 | { |
39 | struct device *dev; | 39 | struct device *dev = NULL; |
40 | loff_t nr; | 40 | loff_t nr = 0; |
41 | 41 | ||
42 | down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); | 42 | down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); |
43 | 43 | if (*offset == 0) | |
44 | nr = *offset; | ||
45 | if (nr == 0) | ||
46 | return SEQ_START_TOKEN; | 44 | return SEQ_START_TOKEN; |
47 | 45 | while (1) { | |
48 | dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, | ||
49 | NULL, qeth_procfile_seq_match); | ||
50 | |||
51 | /* get card at pos *offset */ | ||
52 | nr = *offset; | ||
53 | while (nr-- > 1 && dev) | ||
54 | dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev, | 46 | dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev, |
55 | NULL, qeth_procfile_seq_match); | 47 | NULL, qeth_procfile_seq_match); |
56 | return (void *) dev; | 48 | if (++nr == *offset) |
49 | break; | ||
50 | put_device(dev); | ||
51 | } | ||
52 | return dev; | ||
57 | } | 53 | } |
58 | 54 | ||
59 | static void | 55 | static void |
@@ -66,19 +62,14 @@ static void * | |||
66 | qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) | 62 | qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) |
67 | { | 63 | { |
68 | struct device *prev, *next; | 64 | struct device *prev, *next; |
69 | 65 | ||
70 | if (it == SEQ_START_TOKEN) { | 66 | if (it == SEQ_START_TOKEN) |
71 | next = driver_find_device(&qeth_ccwgroup_driver.driver, | 67 | prev = NULL; |
72 | NULL, NULL, qeth_procfile_seq_match); | 68 | else |
73 | if (next) | 69 | prev = (struct device *) it; |
74 | (*offset)++; | ||
75 | return (void *) next; | ||
76 | } | ||
77 | prev = (struct device *) it; | ||
78 | next = driver_find_device(&qeth_ccwgroup_driver.driver, | 70 | next = driver_find_device(&qeth_ccwgroup_driver.driver, |
79 | prev, NULL, qeth_procfile_seq_match); | 71 | prev, NULL, qeth_procfile_seq_match); |
80 | if (next) | 72 | (*offset)++; |
81 | (*offset)++; | ||
82 | return (void *) next; | 73 | return (void *) next; |
83 | } | 74 | } |
84 | 75 | ||
@@ -87,7 +78,7 @@ qeth_get_router_str(struct qeth_card *card, int ipv) | |||
87 | { | 78 | { |
88 | int routing_type = 0; | 79 | int routing_type = 0; |
89 | 80 | ||
90 | if (ipv == 4){ | 81 | if (ipv == 4) { |
91 | routing_type = card->options.route4.type; | 82 | routing_type = card->options.route4.type; |
92 | } else { | 83 | } else { |
93 | #ifdef CONFIG_QETH_IPV6 | 84 | #ifdef CONFIG_QETH_IPV6 |
@@ -154,6 +145,7 @@ qeth_procfile_seq_show(struct seq_file *s, void *it) | |||
154 | card->qdio.in_buf_pool.buf_count); | 145 | card->qdio.in_buf_pool.buf_count); |
155 | else | 146 | else |
156 | seq_printf(s, " +++ LAN OFFLINE +++\n"); | 147 | seq_printf(s, " +++ LAN OFFLINE +++\n"); |
148 | put_device(device); | ||
157 | } | 149 | } |
158 | return 0; | 150 | return 0; |
159 | } | 151 | } |
@@ -184,51 +176,16 @@ static struct file_operations qeth_procfile_fops = { | |||
184 | static struct proc_dir_entry *qeth_perf_procfile; | 176 | static struct proc_dir_entry *qeth_perf_procfile; |
185 | 177 | ||
186 | #ifdef CONFIG_QETH_PERF_STATS | 178 | #ifdef CONFIG_QETH_PERF_STATS |
187 | |||
188 | static void * | ||
189 | qeth_perf_procfile_seq_start(struct seq_file *s, loff_t *offset) | ||
190 | { | ||
191 | struct device *dev = NULL; | ||
192 | int nr; | ||
193 | |||
194 | down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); | ||
195 | /* get card at pos *offset */ | ||
196 | dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL, | ||
197 | qeth_procfile_seq_match); | ||
198 | |||
199 | /* get card at pos *offset */ | ||
200 | nr = *offset; | ||
201 | while (nr-- > 1 && dev) | ||
202 | dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev, | ||
203 | NULL, qeth_procfile_seq_match); | ||
204 | return (void *) dev; | ||
205 | } | ||
206 | |||
207 | static void | ||
208 | qeth_perf_procfile_seq_stop(struct seq_file *s, void* it) | ||
209 | { | ||
210 | up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); | ||
211 | } | ||
212 | |||
213 | static void * | ||
214 | qeth_perf_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) | ||
215 | { | ||
216 | struct device *prev, *next; | ||
217 | |||
218 | prev = (struct device *) it; | ||
219 | next = driver_find_device(&qeth_ccwgroup_driver.driver, prev, | ||
220 | NULL, qeth_procfile_seq_match); | ||
221 | if (next) | ||
222 | (*offset)++; | ||
223 | return (void *) next; | ||
224 | } | ||
225 | |||
226 | static int | 179 | static int |
227 | qeth_perf_procfile_seq_show(struct seq_file *s, void *it) | 180 | qeth_perf_procfile_seq_show(struct seq_file *s, void *it) |
228 | { | 181 | { |
229 | struct device *device; | 182 | struct device *device; |
230 | struct qeth_card *card; | 183 | struct qeth_card *card; |
231 | 184 | ||
185 | |||
186 | if (it == SEQ_START_TOKEN) | ||
187 | return 0; | ||
188 | |||
232 | device = (struct device *) it; | 189 | device = (struct device *) it; |
233 | card = device->driver_data; | 190 | card = device->driver_data; |
234 | seq_printf(s, "For card with devnos %s/%s/%s (%s):\n", | 191 | seq_printf(s, "For card with devnos %s/%s/%s (%s):\n", |
@@ -295,13 +252,14 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it) | |||
295 | card->perf_stats.outbound_do_qdio_time, | 252 | card->perf_stats.outbound_do_qdio_time, |
296 | card->perf_stats.outbound_do_qdio_cnt | 253 | card->perf_stats.outbound_do_qdio_cnt |
297 | ); | 254 | ); |
255 | put_device(device); | ||
298 | return 0; | 256 | return 0; |
299 | } | 257 | } |
300 | 258 | ||
301 | static struct seq_operations qeth_perf_procfile_seq_ops = { | 259 | static struct seq_operations qeth_perf_procfile_seq_ops = { |
302 | .start = qeth_perf_procfile_seq_start, | 260 | .start = qeth_procfile_seq_start, |
303 | .stop = qeth_perf_procfile_seq_stop, | 261 | .stop = qeth_procfile_seq_stop, |
304 | .next = qeth_perf_procfile_seq_next, | 262 | .next = qeth_procfile_seq_next, |
305 | .show = qeth_perf_procfile_seq_show, | 263 | .show = qeth_perf_procfile_seq_show, |
306 | }; | 264 | }; |
307 | 265 | ||
@@ -324,93 +282,6 @@ static struct file_operations qeth_perf_procfile_fops = { | |||
324 | #define qeth_perf_procfile_created 1 | 282 | #define qeth_perf_procfile_created 1 |
325 | #endif /* CONFIG_QETH_PERF_STATS */ | 283 | #endif /* CONFIG_QETH_PERF_STATS */ |
326 | 284 | ||
327 | /***** /proc/qeth_ipa_takeover *****/ | ||
328 | #define QETH_IPATO_PROCFILE_NAME "qeth_ipa_takeover" | ||
329 | static struct proc_dir_entry *qeth_ipato_procfile; | ||
330 | |||
331 | static void * | ||
332 | qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset) | ||
333 | { | ||
334 | struct device *dev; | ||
335 | loff_t nr; | ||
336 | |||
337 | down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); | ||
338 | /* TODO: finish this */ | ||
339 | /* | ||
340 | * maybe SEQ_SATRT_TOKEN can be returned for offset 0 | ||
341 | * output driver settings then; | ||
342 | * else output setting for respective card | ||
343 | */ | ||
344 | |||
345 | dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL, | ||
346 | qeth_procfile_seq_match); | ||
347 | |||
348 | /* get card at pos *offset */ | ||
349 | nr = *offset; | ||
350 | while (nr-- > 1 && dev) | ||
351 | dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev, | ||
352 | NULL, qeth_procfile_seq_match); | ||
353 | return (void *) dev; | ||
354 | } | ||
355 | |||
356 | static void | ||
357 | qeth_ipato_procfile_seq_stop(struct seq_file *s, void* it) | ||
358 | { | ||
359 | up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); | ||
360 | } | ||
361 | |||
362 | static void * | ||
363 | qeth_ipato_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) | ||
364 | { | ||
365 | struct device *prev, *next; | ||
366 | |||
367 | prev = (struct device *) it; | ||
368 | next = driver_find_device(&qeth_ccwgroup_driver.driver, prev, | ||
369 | NULL, qeth_procfile_seq_match); | ||
370 | if (next) | ||
371 | (*offset)++; | ||
372 | return (void *) next; | ||
373 | } | ||
374 | |||
375 | static int | ||
376 | qeth_ipato_procfile_seq_show(struct seq_file *s, void *it) | ||
377 | { | ||
378 | struct device *device; | ||
379 | struct qeth_card *card; | ||
380 | |||
381 | /* TODO: finish this */ | ||
382 | /* | ||
383 | * maybe SEQ_SATRT_TOKEN can be returned for offset 0 | ||
384 | * output driver settings then; | ||
385 | * else output setting for respective card | ||
386 | */ | ||
387 | device = (struct device *) it; | ||
388 | card = device->driver_data; | ||
389 | |||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | static struct seq_operations qeth_ipato_procfile_seq_ops = { | ||
394 | .start = qeth_ipato_procfile_seq_start, | ||
395 | .stop = qeth_ipato_procfile_seq_stop, | ||
396 | .next = qeth_ipato_procfile_seq_next, | ||
397 | .show = qeth_ipato_procfile_seq_show, | ||
398 | }; | ||
399 | |||
400 | static int | ||
401 | qeth_ipato_procfile_open(struct inode *inode, struct file *file) | ||
402 | { | ||
403 | return seq_open(file, &qeth_ipato_procfile_seq_ops); | ||
404 | } | ||
405 | |||
406 | static struct file_operations qeth_ipato_procfile_fops = { | ||
407 | .owner = THIS_MODULE, | ||
408 | .open = qeth_ipato_procfile_open, | ||
409 | .read = seq_read, | ||
410 | .llseek = seq_lseek, | ||
411 | .release = seq_release, | ||
412 | }; | ||
413 | |||
414 | int __init | 285 | int __init |
415 | qeth_create_procfs_entries(void) | 286 | qeth_create_procfs_entries(void) |
416 | { | 287 | { |
@@ -426,13 +297,7 @@ qeth_create_procfs_entries(void) | |||
426 | qeth_perf_procfile->proc_fops = &qeth_perf_procfile_fops; | 297 | qeth_perf_procfile->proc_fops = &qeth_perf_procfile_fops; |
427 | #endif /* CONFIG_QETH_PERF_STATS */ | 298 | #endif /* CONFIG_QETH_PERF_STATS */ |
428 | 299 | ||
429 | qeth_ipato_procfile = create_proc_entry(QETH_IPATO_PROCFILE_NAME, | ||
430 | S_IFREG | 0444, NULL); | ||
431 | if (qeth_ipato_procfile) | ||
432 | qeth_ipato_procfile->proc_fops = &qeth_ipato_procfile_fops; | ||
433 | |||
434 | if (qeth_procfile && | 300 | if (qeth_procfile && |
435 | qeth_ipato_procfile && | ||
436 | qeth_perf_procfile_created) | 301 | qeth_perf_procfile_created) |
437 | return 0; | 302 | return 0; |
438 | else | 303 | else |
@@ -446,62 +311,5 @@ qeth_remove_procfs_entries(void) | |||
446 | remove_proc_entry(QETH_PROCFILE_NAME, NULL); | 311 | remove_proc_entry(QETH_PROCFILE_NAME, NULL); |
447 | if (qeth_perf_procfile) | 312 | if (qeth_perf_procfile) |
448 | remove_proc_entry(QETH_PERF_PROCFILE_NAME, NULL); | 313 | remove_proc_entry(QETH_PERF_PROCFILE_NAME, NULL); |
449 | if (qeth_ipato_procfile) | ||
450 | remove_proc_entry(QETH_IPATO_PROCFILE_NAME, NULL); | ||
451 | } | 314 | } |
452 | 315 | ||
453 | |||
454 | /* ONLY FOR DEVELOPMENT! -> make it as module */ | ||
455 | /* | ||
456 | static void | ||
457 | qeth_create_sysfs_entries(void) | ||
458 | { | ||
459 | struct device *dev; | ||
460 | |||
461 | down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); | ||
462 | |||
463 | list_for_each_entry(dev, &qeth_ccwgroup_driver.driver.devices, | ||
464 | driver_list) | ||
465 | qeth_create_device_attributes(dev); | ||
466 | |||
467 | up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); | ||
468 | } | ||
469 | |||
470 | static void | ||
471 | qeth_remove_sysfs_entries(void) | ||
472 | { | ||
473 | struct device *dev; | ||
474 | |||
475 | down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); | ||
476 | |||
477 | list_for_each_entry(dev, &qeth_ccwgroup_driver.driver.devices, | ||
478 | driver_list) | ||
479 | qeth_remove_device_attributes(dev); | ||
480 | |||
481 | up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); | ||
482 | } | ||
483 | |||
484 | static int __init | ||
485 | qeth_fs_init(void) | ||
486 | { | ||
487 | printk(KERN_INFO "qeth_fs_init\n"); | ||
488 | qeth_create_procfs_entries(); | ||
489 | qeth_create_sysfs_entries(); | ||
490 | |||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | static void __exit | ||
495 | qeth_fs_exit(void) | ||
496 | { | ||
497 | printk(KERN_INFO "qeth_fs_exit\n"); | ||
498 | qeth_remove_procfs_entries(); | ||
499 | qeth_remove_sysfs_entries(); | ||
500 | } | ||
501 | |||
502 | |||
503 | module_init(qeth_fs_init); | ||
504 | module_exit(qeth_fs_exit); | ||
505 | |||
506 | MODULE_LICENSE("GPL"); | ||
507 | */ | ||
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index f91a02db5743..0ea185f70f75 100644 --- a/drivers/s390/net/qeth_sys.c +++ b/drivers/s390/net/qeth_sys.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * | 2 | * |
3 | * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.55 $) | 3 | * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.60 $) |
4 | * | 4 | * |
5 | * Linux on zSeries OSA Express and HiperSockets support | 5 | * Linux on zSeries OSA Express and HiperSockets support |
6 | * This file contains code related to sysfs. | 6 | * This file contains code related to sysfs. |
@@ -8,7 +8,7 @@ | |||
8 | * Copyright 2000,2003 IBM Corporation | 8 | * Copyright 2000,2003 IBM Corporation |
9 | * | 9 | * |
10 | * Author(s): Thomas Spatzier <tspat@de.ibm.com> | 10 | * Author(s): Thomas Spatzier <tspat@de.ibm.com> |
11 | * Frank Pavlic <pavlic@de.ibm.com> | 11 | * Frank Pavlic <fpavlic@de.ibm.com> |
12 | * | 12 | * |
13 | */ | 13 | */ |
14 | #include <linux/list.h> | 14 | #include <linux/list.h> |
@@ -20,7 +20,7 @@ | |||
20 | #include "qeth_mpc.h" | 20 | #include "qeth_mpc.h" |
21 | #include "qeth_fs.h" | 21 | #include "qeth_fs.h" |
22 | 22 | ||
23 | const char *VERSION_QETH_SYS_C = "$Revision: 1.55 $"; | 23 | const char *VERSION_QETH_SYS_C = "$Revision: 1.60 $"; |
24 | 24 | ||
25 | /*****************************************************************************/ | 25 | /*****************************************************************************/ |
26 | /* */ | 26 | /* */ |
@@ -160,7 +160,7 @@ qeth_dev_portname_store(struct device *dev, struct device_attribute *attr, const | |||
160 | return -EPERM; | 160 | return -EPERM; |
161 | 161 | ||
162 | tmp = strsep((char **) &buf, "\n"); | 162 | tmp = strsep((char **) &buf, "\n"); |
163 | if ((strlen(tmp) > 8) || (strlen(tmp) < 2)) | 163 | if ((strlen(tmp) > 8) || (strlen(tmp) == 0)) |
164 | return -EINVAL; | 164 | return -EINVAL; |
165 | 165 | ||
166 | card->info.portname[0] = strlen(tmp); | 166 | card->info.portname[0] = strlen(tmp); |
@@ -1117,7 +1117,7 @@ qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto, | |||
1117 | start = buf; | 1117 | start = buf; |
1118 | /* get address string */ | 1118 | /* get address string */ |
1119 | end = strchr(start, '/'); | 1119 | end = strchr(start, '/'); |
1120 | if (!end){ | 1120 | if (!end || (end-start >= 49)){ |
1121 | PRINT_WARN("Invalid format for ipato_addx/delx. " | 1121 | PRINT_WARN("Invalid format for ipato_addx/delx. " |
1122 | "Use <ip addr>/<mask bits>\n"); | 1122 | "Use <ip addr>/<mask bits>\n"); |
1123 | return -EINVAL; | 1123 | return -EINVAL; |
diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h index ad33e6f466f1..3c50b6f24f51 100644 --- a/drivers/s390/net/qeth_tso.h +++ b/drivers/s390/net/qeth_tso.h | |||
@@ -1,13 +1,13 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.7 $) | 2 | * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.8 $) |
3 | * | 3 | * |
4 | * Header file for qeth TCP Segmentation Offload support. | 4 | * Header file for qeth TCP Segmentation Offload support. |
5 | * | 5 | * |
6 | * Copyright 2004 IBM Corporation | 6 | * Copyright 2004 IBM Corporation |
7 | * | 7 | * |
8 | * Author(s): Frank Pavlic <pavlic@de.ibm.com> | 8 | * Author(s): Frank Pavlic <fpavlic@de.ibm.com> |
9 | * | 9 | * |
10 | * $Revision: 1.7 $ $Date: 2005/05/04 20:19:18 $ | 10 | * $Revision: 1.8 $ $Date: 2005/05/04 20:19:18 $ |
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | #ifndef __QETH_TSO_H__ | 13 | #ifndef __QETH_TSO_H__ |
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index c218b5c944a6..5e84c5aa7779 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -996,6 +996,20 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
996 | spin_lock_init(&adapter->fsf_req_list_lock); | 996 | spin_lock_init(&adapter->fsf_req_list_lock); |
997 | INIT_LIST_HEAD(&adapter->fsf_req_list_head); | 997 | INIT_LIST_HEAD(&adapter->fsf_req_list_head); |
998 | 998 | ||
999 | /* initialize debug locks */ | ||
1000 | |||
1001 | spin_lock_init(&adapter->erp_dbf_lock); | ||
1002 | spin_lock_init(&adapter->hba_dbf_lock); | ||
1003 | spin_lock_init(&adapter->san_dbf_lock); | ||
1004 | spin_lock_init(&adapter->scsi_dbf_lock); | ||
1005 | |||
1006 | /* initialize error recovery stuff */ | ||
1007 | |||
1008 | rwlock_init(&adapter->erp_lock); | ||
1009 | sema_init(&adapter->erp_ready_sem, 0); | ||
1010 | INIT_LIST_HEAD(&adapter->erp_ready_head); | ||
1011 | INIT_LIST_HEAD(&adapter->erp_running_head); | ||
1012 | |||
999 | /* initialize abort lock */ | 1013 | /* initialize abort lock */ |
1000 | rwlock_init(&adapter->abort_lock); | 1014 | rwlock_init(&adapter->abort_lock); |
1001 | 1015 | ||
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 826fb3b00605..95599719f8ab 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c | |||
@@ -926,7 +926,6 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter) | |||
926 | char dbf_name[DEBUG_MAX_NAME_LEN]; | 926 | char dbf_name[DEBUG_MAX_NAME_LEN]; |
927 | 927 | ||
928 | /* debug feature area which records recovery activity */ | 928 | /* debug feature area which records recovery activity */ |
929 | spin_lock_init(&adapter->erp_dbf_lock); | ||
930 | sprintf(dbf_name, "zfcp_%s_erp", zfcp_get_busid_by_adapter(adapter)); | 929 | sprintf(dbf_name, "zfcp_%s_erp", zfcp_get_busid_by_adapter(adapter)); |
931 | adapter->erp_dbf = debug_register(dbf_name, dbfsize, 2, | 930 | adapter->erp_dbf = debug_register(dbf_name, dbfsize, 2, |
932 | sizeof(struct zfcp_erp_dbf_record)); | 931 | sizeof(struct zfcp_erp_dbf_record)); |
@@ -936,7 +935,6 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter) | |||
936 | debug_set_level(adapter->erp_dbf, 3); | 935 | debug_set_level(adapter->erp_dbf, 3); |
937 | 936 | ||
938 | /* debug feature area which records HBA (FSF and QDIO) conditions */ | 937 | /* debug feature area which records HBA (FSF and QDIO) conditions */ |
939 | spin_lock_init(&adapter->hba_dbf_lock); | ||
940 | sprintf(dbf_name, "zfcp_%s_hba", zfcp_get_busid_by_adapter(adapter)); | 938 | sprintf(dbf_name, "zfcp_%s_hba", zfcp_get_busid_by_adapter(adapter)); |
941 | adapter->hba_dbf = debug_register(dbf_name, dbfsize, 1, | 939 | adapter->hba_dbf = debug_register(dbf_name, dbfsize, 1, |
942 | sizeof(struct zfcp_hba_dbf_record)); | 940 | sizeof(struct zfcp_hba_dbf_record)); |
@@ -947,7 +945,6 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter) | |||
947 | debug_set_level(adapter->hba_dbf, 3); | 945 | debug_set_level(adapter->hba_dbf, 3); |
948 | 946 | ||
949 | /* debug feature area which records SAN command failures and recovery */ | 947 | /* debug feature area which records SAN command failures and recovery */ |
950 | spin_lock_init(&adapter->san_dbf_lock); | ||
951 | sprintf(dbf_name, "zfcp_%s_san", zfcp_get_busid_by_adapter(adapter)); | 948 | sprintf(dbf_name, "zfcp_%s_san", zfcp_get_busid_by_adapter(adapter)); |
952 | adapter->san_dbf = debug_register(dbf_name, dbfsize, 1, | 949 | adapter->san_dbf = debug_register(dbf_name, dbfsize, 1, |
953 | sizeof(struct zfcp_san_dbf_record)); | 950 | sizeof(struct zfcp_san_dbf_record)); |
@@ -958,7 +955,6 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter) | |||
958 | debug_set_level(adapter->san_dbf, 6); | 955 | debug_set_level(adapter->san_dbf, 6); |
959 | 956 | ||
960 | /* debug feature area which records SCSI command failures and recovery */ | 957 | /* debug feature area which records SCSI command failures and recovery */ |
961 | spin_lock_init(&adapter->scsi_dbf_lock); | ||
962 | sprintf(dbf_name, "zfcp_%s_scsi", zfcp_get_busid_by_adapter(adapter)); | 958 | sprintf(dbf_name, "zfcp_%s_scsi", zfcp_get_busid_by_adapter(adapter)); |
963 | adapter->scsi_dbf = debug_register(dbf_name, dbfsize, 1, | 959 | adapter->scsi_dbf = debug_register(dbf_name, dbfsize, 1, |
964 | sizeof(struct zfcp_scsi_dbf_record)); | 960 | sizeof(struct zfcp_scsi_dbf_record)); |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 023f4e558ae4..ee7314d8c2da 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -1071,11 +1071,6 @@ zfcp_erp_thread_setup(struct zfcp_adapter *adapter) | |||
1071 | 1071 | ||
1072 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); | 1072 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); |
1073 | 1073 | ||
1074 | rwlock_init(&adapter->erp_lock); | ||
1075 | INIT_LIST_HEAD(&adapter->erp_ready_head); | ||
1076 | INIT_LIST_HEAD(&adapter->erp_running_head); | ||
1077 | sema_init(&adapter->erp_ready_sem, 0); | ||
1078 | |||
1079 | retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD); | 1074 | retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD); |
1080 | if (retval < 0) { | 1075 | if (retval < 0) { |
1081 | ZFCP_LOG_NORMAL("error: creation of erp thread failed for " | 1076 | ZFCP_LOG_NORMAL("error: creation of erp thread failed for " |
@@ -2248,29 +2243,26 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) | |||
2248 | return retval; | 2243 | return retval; |
2249 | } | 2244 | } |
2250 | 2245 | ||
2251 | /* | ||
2252 | * function: zfcp_fsf_init | ||
2253 | * | ||
2254 | * purpose: initializes FSF operation for the specified adapter | ||
2255 | * | ||
2256 | * returns: 0 - succesful initialization of FSF operation | ||
2257 | * !0 - failed to initialize FSF operation | ||
2258 | */ | ||
2259 | static int | 2246 | static int |
2260 | zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) | 2247 | zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) |
2261 | { | 2248 | { |
2262 | int xconfig, xport; | 2249 | int retval; |
2263 | 2250 | ||
2264 | if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | 2251 | if ((atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, |
2265 | &erp_action->adapter->status)) { | 2252 | &erp_action->adapter->status)) && |
2253 | (erp_action->adapter->adapter_features & | ||
2254 | FSF_FEATURE_HBAAPI_MANAGEMENT)) { | ||
2266 | zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); | 2255 | zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); |
2267 | atomic_set(&erp_action->adapter->erp_counter, 0); | 2256 | atomic_set(&erp_action->adapter->erp_counter, 0); |
2268 | return ZFCP_ERP_FAILED; | 2257 | return ZFCP_ERP_FAILED; |
2269 | } | 2258 | } |
2270 | 2259 | ||
2271 | xconfig = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); | 2260 | retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); |
2272 | xport = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); | 2261 | if (retval == ZFCP_ERP_FAILED) |
2273 | if ((xconfig == ZFCP_ERP_FAILED) || (xport == ZFCP_ERP_FAILED)) | 2262 | return ZFCP_ERP_FAILED; |
2263 | |||
2264 | retval = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); | ||
2265 | if (retval == ZFCP_ERP_FAILED) | ||
2274 | return ZFCP_ERP_FAILED; | 2266 | return ZFCP_ERP_FAILED; |
2275 | 2267 | ||
2276 | return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action); | 2268 | return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action); |
@@ -2359,41 +2351,29 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action) | |||
2359 | static int | 2351 | static int |
2360 | zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) | 2352 | zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) |
2361 | { | 2353 | { |
2362 | int retval = ZFCP_ERP_SUCCEEDED; | 2354 | int ret; |
2363 | int retries; | 2355 | int retries; |
2364 | int sleep; | 2356 | int sleep; |
2365 | struct zfcp_adapter *adapter = erp_action->adapter; | 2357 | struct zfcp_adapter *adapter = erp_action->adapter; |
2366 | 2358 | ||
2367 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); | 2359 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); |
2368 | 2360 | ||
2369 | for (retries = 0; ; retries++) { | 2361 | retries = 0; |
2370 | ZFCP_LOG_DEBUG("Doing exchange port data\n"); | 2362 | do { |
2363 | write_lock(&adapter->erp_lock); | ||
2371 | zfcp_erp_action_to_running(erp_action); | 2364 | zfcp_erp_action_to_running(erp_action); |
2365 | write_unlock(&adapter->erp_lock); | ||
2372 | zfcp_erp_timeout_init(erp_action); | 2366 | zfcp_erp_timeout_init(erp_action); |
2373 | if (zfcp_fsf_exchange_port_data(erp_action, adapter, NULL)) { | 2367 | ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL); |
2374 | retval = ZFCP_ERP_FAILED; | 2368 | if (ret == -EOPNOTSUPP) { |
2375 | debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf"); | 2369 | debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp"); |
2376 | ZFCP_LOG_INFO("error: initiation of exchange of " | 2370 | return ZFCP_ERP_SUCCEEDED; |
2377 | "port data failed for adapter %s\n", | 2371 | } else if (ret) { |
2378 | zfcp_get_busid_by_adapter(adapter)); | 2372 | debug_text_event(adapter->erp_dbf, 3, "a_xport_failed"); |
2379 | break; | 2373 | return ZFCP_ERP_FAILED; |
2380 | } | 2374 | } |
2381 | debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok"); | 2375 | debug_text_event(adapter->erp_dbf, 6, "a_xport_ok"); |
2382 | ZFCP_LOG_DEBUG("Xchange underway\n"); | ||
2383 | 2376 | ||
2384 | /* | ||
2385 | * Why this works: | ||
2386 | * Both the normal completion handler as well as the timeout | ||
2387 | * handler will do an 'up' when the 'exchange port data' | ||
2388 | * request completes or times out. Thus, the signal to go on | ||
2389 | * won't be lost utilizing this semaphore. | ||
2390 | * Furthermore, this 'adapter_reopen' action is | ||
2391 | * guaranteed to be the only action being there (highest action | ||
2392 | * which prevents other actions from being created). | ||
2393 | * Resulting from that, the wake signal recognized here | ||
2394 | * _must_ be the one belonging to the 'exchange port | ||
2395 | * data' request. | ||
2396 | */ | ||
2397 | down(&adapter->erp_ready_sem); | 2377 | down(&adapter->erp_ready_sem); |
2398 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { | 2378 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { |
2399 | ZFCP_LOG_INFO("error: exchange of port data " | 2379 | ZFCP_LOG_INFO("error: exchange of port data " |
@@ -2401,29 +2381,19 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) | |||
2401 | zfcp_get_busid_by_adapter(adapter)); | 2381 | zfcp_get_busid_by_adapter(adapter)); |
2402 | break; | 2382 | break; |
2403 | } | 2383 | } |
2404 | |||
2405 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | 2384 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, |
2406 | &adapter->status)) | 2385 | &adapter->status)) |
2407 | break; | 2386 | break; |
2408 | 2387 | ||
2409 | ZFCP_LOG_DEBUG("host connection still initialising... " | 2388 | if (retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES) { |
2410 | "waiting and retrying...\n"); | 2389 | sleep = ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP; |
2411 | /* sleep a little bit before retry */ | 2390 | retries++; |
2412 | sleep = retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES ? | 2391 | } else |
2413 | ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP : | 2392 | sleep = ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP; |
2414 | ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP; | 2393 | schedule_timeout(sleep); |
2415 | msleep(jiffies_to_msecs(sleep)); | 2394 | } while (1); |
2416 | } | ||
2417 | |||
2418 | if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | ||
2419 | &adapter->status)) { | ||
2420 | ZFCP_LOG_INFO("error: exchange of port data for " | ||
2421 | "adapter %s failed\n", | ||
2422 | zfcp_get_busid_by_adapter(adapter)); | ||
2423 | retval = ZFCP_ERP_FAILED; | ||
2424 | } | ||
2425 | 2395 | ||
2426 | return retval; | 2396 | return ZFCP_ERP_SUCCEEDED; |
2427 | } | 2397 | } |
2428 | 2398 | ||
2429 | /* | 2399 | /* |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 3b0fc1163f5f..59587951c847 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -554,6 +554,17 @@ static void | |||
554 | zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter, | 554 | zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter, |
555 | struct fsf_link_down_info *link_down) | 555 | struct fsf_link_down_info *link_down) |
556 | { | 556 | { |
557 | if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | ||
558 | &adapter->status)) | ||
559 | return; | ||
560 | |||
561 | atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); | ||
562 | |||
563 | if (link_down == NULL) { | ||
564 | zfcp_erp_adapter_reopen(adapter, 0); | ||
565 | return; | ||
566 | } | ||
567 | |||
557 | switch (link_down->error_code) { | 568 | switch (link_down->error_code) { |
558 | case FSF_PSQ_LINK_NO_LIGHT: | 569 | case FSF_PSQ_LINK_NO_LIGHT: |
559 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | 570 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " |
@@ -634,20 +645,15 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter, | |||
634 | link_down->explanation_code, | 645 | link_down->explanation_code, |
635 | link_down->vendor_specific_code); | 646 | link_down->vendor_specific_code); |
636 | 647 | ||
637 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | 648 | switch (link_down->error_code) { |
638 | &adapter->status)) { | 649 | case FSF_PSQ_LINK_NO_LIGHT: |
639 | atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | 650 | case FSF_PSQ_LINK_WRAP_PLUG: |
640 | &adapter->status); | 651 | case FSF_PSQ_LINK_NO_FCP: |
641 | switch (link_down->error_code) { | 652 | case FSF_PSQ_LINK_FIRMWARE_UPDATE: |
642 | case FSF_PSQ_LINK_NO_LIGHT: | 653 | zfcp_erp_adapter_reopen(adapter, 0); |
643 | case FSF_PSQ_LINK_WRAP_PLUG: | 654 | break; |
644 | case FSF_PSQ_LINK_NO_FCP: | 655 | default: |
645 | case FSF_PSQ_LINK_FIRMWARE_UPDATE: | 656 | zfcp_erp_adapter_failed(adapter); |
646 | zfcp_erp_adapter_reopen(adapter, 0); | ||
647 | break; | ||
648 | default: | ||
649 | zfcp_erp_adapter_failed(adapter); | ||
650 | } | ||
651 | } | 657 | } |
652 | } | 658 | } |
653 | 659 | ||
@@ -919,30 +925,36 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) | |||
919 | case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: | 925 | case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: |
920 | ZFCP_LOG_INFO("Physical link to adapter %s is down\n", | 926 | ZFCP_LOG_INFO("Physical link to adapter %s is down\n", |
921 | zfcp_get_busid_by_adapter(adapter)); | 927 | zfcp_get_busid_by_adapter(adapter)); |
928 | zfcp_fsf_link_down_info_eval(adapter, | ||
929 | (struct fsf_link_down_info *) | ||
930 | &status_buffer->payload); | ||
922 | break; | 931 | break; |
923 | case FSF_STATUS_READ_SUB_FDISC_FAILED: | 932 | case FSF_STATUS_READ_SUB_FDISC_FAILED: |
924 | ZFCP_LOG_INFO("Local link to adapter %s is down " | 933 | ZFCP_LOG_INFO("Local link to adapter %s is down " |
925 | "due to failed FDISC login\n", | 934 | "due to failed FDISC login\n", |
926 | zfcp_get_busid_by_adapter(adapter)); | 935 | zfcp_get_busid_by_adapter(adapter)); |
936 | zfcp_fsf_link_down_info_eval(adapter, | ||
937 | (struct fsf_link_down_info *) | ||
938 | &status_buffer->payload); | ||
927 | break; | 939 | break; |
928 | case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE: | 940 | case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE: |
929 | ZFCP_LOG_INFO("Local link to adapter %s is down " | 941 | ZFCP_LOG_INFO("Local link to adapter %s is down " |
930 | "due to firmware update on adapter\n", | 942 | "due to firmware update on adapter\n", |
931 | zfcp_get_busid_by_adapter(adapter)); | 943 | zfcp_get_busid_by_adapter(adapter)); |
944 | zfcp_fsf_link_down_info_eval(adapter, NULL); | ||
932 | break; | 945 | break; |
933 | default: | 946 | default: |
934 | ZFCP_LOG_INFO("Local link to adapter %s is down " | 947 | ZFCP_LOG_INFO("Local link to adapter %s is down " |
935 | "due to unknown reason\n", | 948 | "due to unknown reason\n", |
936 | zfcp_get_busid_by_adapter(adapter)); | 949 | zfcp_get_busid_by_adapter(adapter)); |
950 | zfcp_fsf_link_down_info_eval(adapter, NULL); | ||
937 | }; | 951 | }; |
938 | zfcp_fsf_link_down_info_eval(adapter, | ||
939 | (struct fsf_link_down_info *) &status_buffer->payload); | ||
940 | break; | 952 | break; |
941 | 953 | ||
942 | case FSF_STATUS_READ_LINK_UP: | 954 | case FSF_STATUS_READ_LINK_UP: |
943 | ZFCP_LOG_NORMAL("Local link to adapter %s was replugged. " | 955 | ZFCP_LOG_NORMAL("Local link to adapter %s was replugged. " |
944 | "Restarting operations on this adapter\n", | 956 | "Restarting operations on this adapter\n", |
945 | zfcp_get_busid_by_adapter(adapter)); | 957 | zfcp_get_busid_by_adapter(adapter)); |
946 | /* All ports should be marked as ready to run again */ | 958 | /* All ports should be marked as ready to run again */ |
947 | zfcp_erp_modify_adapter_status(adapter, | 959 | zfcp_erp_modify_adapter_status(adapter, |
948 | ZFCP_STATUS_COMMON_RUNNING, | 960 | ZFCP_STATUS_COMMON_RUNNING, |
@@ -2191,13 +2203,10 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, | |||
2191 | return -EOPNOTSUPP; | 2203 | return -EOPNOTSUPP; |
2192 | } | 2204 | } |
2193 | 2205 | ||
2194 | timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL); | ||
2195 | if (!timer) | ||
2196 | return -ENOMEM; | ||
2197 | |||
2198 | /* setup new FSF request */ | 2206 | /* setup new FSF request */ |
2199 | retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, | 2207 | retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, |
2200 | 0, 0, &lock_flags, &fsf_req); | 2208 | erp_action ? ZFCP_REQ_AUTO_CLEANUP : 0, |
2209 | 0, &lock_flags, &fsf_req); | ||
2201 | if (retval < 0) { | 2210 | if (retval < 0) { |
2202 | ZFCP_LOG_INFO("error: Out of resources. Could not create an " | 2211 | ZFCP_LOG_INFO("error: Out of resources. Could not create an " |
2203 | "exchange port data request for" | 2212 | "exchange port data request for" |
@@ -2205,25 +2214,33 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, | |||
2205 | zfcp_get_busid_by_adapter(adapter)); | 2214 | zfcp_get_busid_by_adapter(adapter)); |
2206 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, | 2215 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, |
2207 | lock_flags); | 2216 | lock_flags); |
2208 | goto out; | 2217 | return retval; |
2209 | } | ||
2210 | |||
2211 | if (erp_action) { | ||
2212 | erp_action->fsf_req = fsf_req; | ||
2213 | fsf_req->erp_action = erp_action; | ||
2214 | } | 2218 | } |
2215 | 2219 | ||
2216 | if (data) | 2220 | if (data) |
2217 | fsf_req->data = (unsigned long) data; | 2221 | fsf_req->data = (unsigned long) data; |
2218 | 2222 | ||
2219 | sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); | 2223 | sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); |
2220 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | 2224 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; |
2221 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 2225 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
2222 | 2226 | ||
2223 | init_timer(timer); | 2227 | if (erp_action) { |
2224 | timer->function = zfcp_fsf_request_timeout_handler; | 2228 | erp_action->fsf_req = fsf_req; |
2225 | timer->data = (unsigned long) adapter; | 2229 | fsf_req->erp_action = erp_action; |
2226 | timer->expires = ZFCP_FSF_REQUEST_TIMEOUT; | 2230 | timer = &erp_action->timer; |
2231 | } else { | ||
2232 | timer = kmalloc(sizeof(struct timer_list), GFP_ATOMIC); | ||
2233 | if (!timer) { | ||
2234 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, | ||
2235 | lock_flags); | ||
2236 | zfcp_fsf_req_free(fsf_req); | ||
2237 | return -ENOMEM; | ||
2238 | } | ||
2239 | init_timer(timer); | ||
2240 | timer->function = zfcp_fsf_request_timeout_handler; | ||
2241 | timer->data = (unsigned long) adapter; | ||
2242 | timer->expires = ZFCP_FSF_REQUEST_TIMEOUT; | ||
2243 | } | ||
2227 | 2244 | ||
2228 | retval = zfcp_fsf_req_send(fsf_req, timer); | 2245 | retval = zfcp_fsf_req_send(fsf_req, timer); |
2229 | if (retval) { | 2246 | if (retval) { |
@@ -2233,23 +2250,22 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, | |||
2233 | zfcp_fsf_req_free(fsf_req); | 2250 | zfcp_fsf_req_free(fsf_req); |
2234 | if (erp_action) | 2251 | if (erp_action) |
2235 | erp_action->fsf_req = NULL; | 2252 | erp_action->fsf_req = NULL; |
2253 | else | ||
2254 | kfree(timer); | ||
2236 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, | 2255 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, |
2237 | lock_flags); | 2256 | lock_flags); |
2238 | goto out; | 2257 | return retval; |
2239 | } | 2258 | } |
2240 | 2259 | ||
2241 | ZFCP_LOG_DEBUG("Exchange Port Data request initiated (adapter %s)\n", | 2260 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); |
2242 | zfcp_get_busid_by_adapter(adapter)); | ||
2243 | |||
2244 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, | ||
2245 | lock_flags); | ||
2246 | 2261 | ||
2247 | wait_event(fsf_req->completion_wq, | 2262 | if (!erp_action) { |
2248 | fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); | 2263 | wait_event(fsf_req->completion_wq, |
2249 | del_timer_sync(timer); | 2264 | fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); |
2250 | zfcp_fsf_req_free(fsf_req); | 2265 | del_timer_sync(timer); |
2251 | out: | 2266 | zfcp_fsf_req_free(fsf_req); |
2252 | kfree(timer); | 2267 | kfree(timer); |
2268 | } | ||
2253 | return retval; | 2269 | return retval; |
2254 | } | 2270 | } |
2255 | 2271 | ||
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 3dcd1bfba3b4..66608d13a634 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -179,7 +179,7 @@ zfcp_scsi_slave_alloc(struct scsi_device *sdp) | |||
179 | struct zfcp_adapter *adapter; | 179 | struct zfcp_adapter *adapter; |
180 | struct zfcp_unit *unit; | 180 | struct zfcp_unit *unit; |
181 | unsigned long flags; | 181 | unsigned long flags; |
182 | int retval = -ENODEV; | 182 | int retval = -ENXIO; |
183 | 183 | ||
184 | adapter = (struct zfcp_adapter *) sdp->host->hostdata[0]; | 184 | adapter = (struct zfcp_adapter *) sdp->host->hostdata[0]; |
185 | if (!adapter) | 185 | if (!adapter) |