diff options
author | Frank Pavlic <fpavlic@de.ibm.com> | 2006-02-07 11:04:38 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2006-02-17 16:16:39 -0500 |
commit | 66cc5d5aee1ea427b3aeacdabd006a4195c81eee (patch) | |
tree | 8a2a5c973ef0be5b344b4281eb72e12b5eaaacca | |
parent | 0d613a27cc753bfacd20e6eaa2183bb7fef4c76e (diff) |
[PATCH] s390: some qeth driver fixes
[patch 2/2] s390: some qeth driver fixes
From: Frank Pavlic <fpavlic@de.ibm.com>
- fixed kernel panic when using EDDP support in Layer 2 mode
- NULL pointer exception in qeth_set_offline fixed.
- setting EDDP in Layer 2 mode did not set NETIF_F_(SG/TSO)
flags when device became online.
- use sscanf for parsing and converting IPv4 addresses
from string to __u8 values.
- qeth_string_to_ipaddr6 fixed. in case of double colon
the converted IPv6 address out from the string was not correct
in previous implementation.
Signed-off-by: Frank Pavlic <fpavlic@de.ibm.com>
diffstat:
qeth.h | 112 +++++++++++++++++++++++++-----------------------------------
qeth_eddp.c | 11 ++++-
qeth_main.c | 17 +++------
3 files changed, 63 insertions(+), 77 deletions(-)
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
-rw-r--r-- | drivers/s390/net/qeth.h | 112 | ||||
-rw-r--r-- | drivers/s390/net/qeth_eddp.c | 11 | ||||
-rw-r--r-- | drivers/s390/net/qeth_main.c | 17 |
3 files changed, 63 insertions, 77 deletions
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index 9a064d4727ad..4df0fcd7b10b 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h | |||
@@ -1076,16 +1076,6 @@ qeth_get_qdio_q_format(struct qeth_card *card) | |||
1076 | } | 1076 | } |
1077 | 1077 | ||
1078 | static inline int | 1078 | static inline int |
1079 | qeth_isdigit(char * buf) | ||
1080 | { | ||
1081 | while (*buf) { | ||
1082 | if (!isdigit(*buf++)) | ||
1083 | return 0; | ||
1084 | } | ||
1085 | return 1; | ||
1086 | } | ||
1087 | |||
1088 | static inline int | ||
1089 | qeth_isxdigit(char * buf) | 1079 | qeth_isxdigit(char * buf) |
1090 | { | 1080 | { |
1091 | while (*buf) { | 1081 | while (*buf) { |
@@ -1104,33 +1094,17 @@ qeth_ipaddr4_to_string(const __u8 *addr, char *buf) | |||
1104 | static inline int | 1094 | static inline int |
1105 | qeth_string_to_ipaddr4(const char *buf, __u8 *addr) | 1095 | qeth_string_to_ipaddr4(const char *buf, __u8 *addr) |
1106 | { | 1096 | { |
1107 | const char *start, *end; | 1097 | int count = 0, rc = 0; |
1108 | char abuf[4]; | 1098 | int in[4]; |
1109 | char *tmp; | 1099 | |
1110 | int len; | 1100 | rc = sscanf(buf, "%d.%d.%d.%d%n", |
1111 | int i; | 1101 | &in[0], &in[1], &in[2], &in[3], &count); |
1112 | 1102 | if (rc != 4 || count) | |
1113 | start = buf; | 1103 | return -EINVAL; |
1114 | for (i = 0; i < 4; i++) { | 1104 | for (count = 0; count < 4; count++) { |
1115 | if (i == 3) { | 1105 | if (in[count] > 255) |
1116 | end = strchr(start,0xa); | ||
1117 | if (end) | ||
1118 | len = end - start; | ||
1119 | else | ||
1120 | len = strlen(start); | ||
1121 | } | ||
1122 | else { | ||
1123 | end = strchr(start, '.'); | ||
1124 | len = end - start; | ||
1125 | } | ||
1126 | if ((len <= 0) || (len > 3)) | ||
1127 | return -EINVAL; | ||
1128 | memset(abuf, 0, 4); | ||
1129 | strncpy(abuf, start, len); | ||
1130 | if (!qeth_isdigit(abuf)) | ||
1131 | return -EINVAL; | 1106 | return -EINVAL; |
1132 | addr[i] = simple_strtoul(abuf, &tmp, 10); | 1107 | addr[count] = in[count]; |
1133 | start = end + 1; | ||
1134 | } | 1108 | } |
1135 | return 0; | 1109 | return 0; |
1136 | } | 1110 | } |
@@ -1149,36 +1123,44 @@ qeth_ipaddr6_to_string(const __u8 *addr, char *buf) | |||
1149 | static inline int | 1123 | static inline int |
1150 | qeth_string_to_ipaddr6(const char *buf, __u8 *addr) | 1124 | qeth_string_to_ipaddr6(const char *buf, __u8 *addr) |
1151 | { | 1125 | { |
1152 | const char *start, *end; | 1126 | char *end, *start; |
1153 | u16 *tmp_addr; | 1127 | __u16 *in; |
1154 | char abuf[5]; | 1128 | char num[5]; |
1155 | char *tmp; | 1129 | int num2, cnt, out, found, save_cnt; |
1156 | int len; | 1130 | unsigned short in_tmp[8] = {0, }; |
1157 | int i; | 1131 | |
1158 | 1132 | cnt = out = found = save_cnt = num2 = 0; | |
1159 | tmp_addr = (u16 *)addr; | 1133 | end = start = (char *) buf; |
1160 | start = buf; | 1134 | in = (__u16 *) addr; |
1161 | for (i = 0; i < 8; i++) { | 1135 | memset(in, 0, 16); |
1162 | if (i == 7) { | 1136 | while (end) { |
1163 | end = strchr(start,0xa); | 1137 | end = strchr(end,':'); |
1164 | if (end) | 1138 | if (end == NULL) { |
1165 | len = end - start; | 1139 | end = (char *)buf + (strlen(buf)); |
1166 | else | 1140 | out = 1; |
1167 | len = strlen(start); | 1141 | } |
1168 | } | 1142 | if ((end - start)) { |
1169 | else { | 1143 | memset(num, 0, 5); |
1170 | end = strchr(start, ':'); | 1144 | memcpy(num, start, end - start); |
1171 | len = end - start; | 1145 | if (!qeth_isxdigit(num)) |
1146 | return -EINVAL; | ||
1147 | sscanf(start, "%x", &num2); | ||
1148 | if (found) | ||
1149 | in_tmp[save_cnt++] = num2; | ||
1150 | else | ||
1151 | in[cnt++] = num2; | ||
1152 | if (out) | ||
1153 | break; | ||
1154 | } else { | ||
1155 | if (found) | ||
1156 | return -EINVAL; | ||
1157 | found = 1; | ||
1172 | } | 1158 | } |
1173 | if ((len <= 0) || (len > 4)) | 1159 | start = ++end; |
1174 | return -EINVAL; | 1160 | } |
1175 | memset(abuf, 0, 5); | 1161 | cnt = 7; |
1176 | strncpy(abuf, start, len); | 1162 | while (save_cnt) |
1177 | if (!qeth_isxdigit(abuf)) | 1163 | in[cnt--] = in_tmp[--save_cnt]; |
1178 | return -EINVAL; | ||
1179 | tmp_addr[i] = simple_strtoul(abuf, &tmp, 16); | ||
1180 | start = end + 1; | ||
1181 | } | ||
1182 | return 0; | 1164 | return 0; |
1183 | } | 1165 | } |
1184 | 1166 | ||
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c index b02313127780..82cb4af2f0e7 100644 --- a/drivers/s390/net/qeth_eddp.c +++ b/drivers/s390/net/qeth_eddp.c | |||
@@ -59,8 +59,7 @@ qeth_eddp_free_context(struct qeth_eddp_context *ctx) | |||
59 | for (i = 0; i < ctx->num_pages; ++i) | 59 | for (i = 0; i < ctx->num_pages; ++i) |
60 | free_page((unsigned long)ctx->pages[i]); | 60 | free_page((unsigned long)ctx->pages[i]); |
61 | kfree(ctx->pages); | 61 | kfree(ctx->pages); |
62 | if (ctx->elements != NULL) | 62 | kfree(ctx->elements); |
63 | kfree(ctx->elements); | ||
64 | kfree(ctx); | 63 | kfree(ctx); |
65 | } | 64 | } |
66 | 65 | ||
@@ -413,6 +412,13 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, | |||
413 | 412 | ||
414 | QETH_DBF_TEXT(trace, 5, "eddpftcp"); | 413 | QETH_DBF_TEXT(trace, 5, "eddpftcp"); |
415 | eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl; | 414 | eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl; |
415 | if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) { | ||
416 | eddp->skb_offset += sizeof(struct ethhdr); | ||
417 | #ifdef CONFIG_QETH_VLAN | ||
418 | if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) | ||
419 | eddp->skb_offset += VLAN_HLEN; | ||
420 | #endif /* CONFIG_QETH_VLAN */ | ||
421 | } | ||
416 | tcph = eddp->skb->h.th; | 422 | tcph = eddp->skb->h.th; |
417 | while (eddp->skb_offset < eddp->skb->len) { | 423 | while (eddp->skb_offset < eddp->skb->len) { |
418 | data_len = min((int)skb_shinfo(eddp->skb)->tso_size, | 424 | data_len = min((int)skb_shinfo(eddp->skb)->tso_size, |
@@ -483,6 +489,7 @@ qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, | |||
483 | return -ENOMEM; | 489 | return -ENOMEM; |
484 | } | 490 | } |
485 | if (qhdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) { | 491 | if (qhdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) { |
492 | skb->mac.raw = (skb->data) + sizeof(struct qeth_hdr); | ||
486 | memcpy(&eddp->mac, eth_hdr(skb), ETH_HLEN); | 493 | memcpy(&eddp->mac, eth_hdr(skb), ETH_HLEN); |
487 | #ifdef CONFIG_QETH_VLAN | 494 | #ifdef CONFIG_QETH_VLAN |
488 | if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) { | 495 | if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) { |
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 410abeada6c4..dba7f7f02e79 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c | |||
@@ -516,7 +516,8 @@ __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode) | |||
516 | QETH_DBF_TEXT(setup, 3, "setoffl"); | 516 | QETH_DBF_TEXT(setup, 3, "setoffl"); |
517 | QETH_DBF_HEX(setup, 3, &card, sizeof(void *)); | 517 | QETH_DBF_HEX(setup, 3, &card, sizeof(void *)); |
518 | 518 | ||
519 | netif_carrier_off(card->dev); | 519 | if (card->dev && netif_carrier_ok(card->dev)) |
520 | netif_carrier_off(card->dev); | ||
520 | recover_flag = card->state; | 521 | recover_flag = card->state; |
521 | if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){ | 522 | if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){ |
522 | PRINT_WARN("Stopping card %s interrupted by user!\n", | 523 | PRINT_WARN("Stopping card %s interrupted by user!\n", |
@@ -1679,6 +1680,7 @@ qeth_cmd_timeout(unsigned long data) | |||
1679 | spin_unlock_irqrestore(&reply->card->lock, flags); | 1680 | spin_unlock_irqrestore(&reply->card->lock, flags); |
1680 | } | 1681 | } |
1681 | 1682 | ||
1683 | |||
1682 | static struct qeth_ipa_cmd * | 1684 | static struct qeth_ipa_cmd * |
1683 | qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) | 1685 | qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) |
1684 | { | 1686 | { |
@@ -1699,7 +1701,8 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) | |||
1699 | QETH_CARD_IFNAME(card), | 1701 | QETH_CARD_IFNAME(card), |
1700 | card->info.chpid); | 1702 | card->info.chpid); |
1701 | card->lan_online = 0; | 1703 | card->lan_online = 0; |
1702 | netif_carrier_off(card->dev); | 1704 | if (card->dev && netif_carrier_ok(card->dev)) |
1705 | netif_carrier_off(card->dev); | ||
1703 | return NULL; | 1706 | return NULL; |
1704 | case IPA_CMD_STARTLAN: | 1707 | case IPA_CMD_STARTLAN: |
1705 | PRINT_INFO("Link reestablished on %s " | 1708 | PRINT_INFO("Link reestablished on %s " |
@@ -5562,7 +5565,7 @@ qeth_set_multicast_list(struct net_device *dev) | |||
5562 | if (card->info.type == QETH_CARD_TYPE_OSN) | 5565 | if (card->info.type == QETH_CARD_TYPE_OSN) |
5563 | return ; | 5566 | return ; |
5564 | 5567 | ||
5565 | QETH_DBF_TEXT(trace,3,"setmulti"); | 5568 | QETH_DBF_TEXT(trace, 3, "setmulti"); |
5566 | qeth_delete_mc_addresses(card); | 5569 | qeth_delete_mc_addresses(card); |
5567 | if (card->options.layer2) { | 5570 | if (card->options.layer2) { |
5568 | qeth_layer2_add_multicast(card); | 5571 | qeth_layer2_add_multicast(card); |
@@ -5579,7 +5582,6 @@ out: | |||
5579 | return; | 5582 | return; |
5580 | if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0) | 5583 | if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0) |
5581 | schedule_work(&card->kernel_thread_starter); | 5584 | schedule_work(&card->kernel_thread_starter); |
5582 | |||
5583 | } | 5585 | } |
5584 | 5586 | ||
5585 | static int | 5587 | static int |
@@ -7452,6 +7454,7 @@ qeth_softsetup_card(struct qeth_card *card) | |||
7452 | card->lan_online = 1; | 7454 | card->lan_online = 1; |
7453 | if (card->info.type==QETH_CARD_TYPE_OSN) | 7455 | if (card->info.type==QETH_CARD_TYPE_OSN) |
7454 | goto out; | 7456 | goto out; |
7457 | qeth_set_large_send(card, card->options.large_send); | ||
7455 | if (card->options.layer2) { | 7458 | if (card->options.layer2) { |
7456 | card->dev->features |= | 7459 | card->dev->features |= |
7457 | NETIF_F_HW_VLAN_FILTER | | 7460 | NETIF_F_HW_VLAN_FILTER | |
@@ -7468,12 +7471,6 @@ qeth_softsetup_card(struct qeth_card *card) | |||
7468 | #endif | 7471 | #endif |
7469 | goto out; | 7472 | goto out; |
7470 | } | 7473 | } |
7471 | if ((card->options.large_send == QETH_LARGE_SEND_EDDP) || | ||
7472 | (card->options.large_send == QETH_LARGE_SEND_TSO)) | ||
7473 | card->dev->features |= NETIF_F_TSO | NETIF_F_SG; | ||
7474 | else | ||
7475 | card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG); | ||
7476 | |||
7477 | if ((rc = qeth_setadapter_parms(card))) | 7474 | if ((rc = qeth_setadapter_parms(card))) |
7478 | QETH_DBF_TEXT_(setup, 2, "2err%d", rc); | 7475 | QETH_DBF_TEXT_(setup, 2, "2err%d", rc); |
7479 | if ((rc = qeth_start_ipassists(card))) | 7476 | if ((rc = qeth_start_ipassists(card))) |