mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-09-22 22:11:38 +08:00
[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>
This commit is contained in:
parent
0d613a27cc
commit
66cc5d5aee
@ -1075,16 +1075,6 @@ qeth_get_qdio_q_format(struct qeth_card *card)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
|
||||||
qeth_isdigit(char * buf)
|
|
||||||
{
|
|
||||||
while (*buf) {
|
|
||||||
if (!isdigit(*buf++))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
qeth_isxdigit(char * buf)
|
qeth_isxdigit(char * buf)
|
||||||
{
|
{
|
||||||
@ -1104,33 +1094,17 @@ qeth_ipaddr4_to_string(const __u8 *addr, char *buf)
|
|||||||
static inline int
|
static inline int
|
||||||
qeth_string_to_ipaddr4(const char *buf, __u8 *addr)
|
qeth_string_to_ipaddr4(const char *buf, __u8 *addr)
|
||||||
{
|
{
|
||||||
const char *start, *end;
|
int count = 0, rc = 0;
|
||||||
char abuf[4];
|
int in[4];
|
||||||
char *tmp;
|
|
||||||
int len;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
start = buf;
|
rc = sscanf(buf, "%d.%d.%d.%d%n",
|
||||||
for (i = 0; i < 4; i++) {
|
&in[0], &in[1], &in[2], &in[3], &count);
|
||||||
if (i == 3) {
|
if (rc != 4 || count)
|
||||||
end = strchr(start,0xa);
|
return -EINVAL;
|
||||||
if (end)
|
for (count = 0; count < 4; count++) {
|
||||||
len = end - start;
|
if (in[count] > 255)
|
||||||
else
|
|
||||||
len = strlen(start);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
end = strchr(start, '.');
|
|
||||||
len = end - start;
|
|
||||||
}
|
|
||||||
if ((len <= 0) || (len > 3))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
memset(abuf, 0, 4);
|
addr[count] = in[count];
|
||||||
strncpy(abuf, start, len);
|
|
||||||
if (!qeth_isdigit(abuf))
|
|
||||||
return -EINVAL;
|
|
||||||
addr[i] = simple_strtoul(abuf, &tmp, 10);
|
|
||||||
start = end + 1;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1149,36 +1123,44 @@ qeth_ipaddr6_to_string(const __u8 *addr, char *buf)
|
|||||||
static inline int
|
static inline int
|
||||||
qeth_string_to_ipaddr6(const char *buf, __u8 *addr)
|
qeth_string_to_ipaddr6(const char *buf, __u8 *addr)
|
||||||
{
|
{
|
||||||
const char *start, *end;
|
char *end, *start;
|
||||||
u16 *tmp_addr;
|
__u16 *in;
|
||||||
char abuf[5];
|
char num[5];
|
||||||
char *tmp;
|
int num2, cnt, out, found, save_cnt;
|
||||||
int len;
|
unsigned short in_tmp[8] = {0, };
|
||||||
int i;
|
|
||||||
|
|
||||||
tmp_addr = (u16 *)addr;
|
cnt = out = found = save_cnt = num2 = 0;
|
||||||
start = buf;
|
end = start = (char *) buf;
|
||||||
for (i = 0; i < 8; i++) {
|
in = (__u16 *) addr;
|
||||||
if (i == 7) {
|
memset(in, 0, 16);
|
||||||
end = strchr(start,0xa);
|
while (end) {
|
||||||
if (end)
|
end = strchr(end,':');
|
||||||
len = end - start;
|
if (end == NULL) {
|
||||||
else
|
end = (char *)buf + (strlen(buf));
|
||||||
len = strlen(start);
|
out = 1;
|
||||||
|
}
|
||||||
|
if ((end - start)) {
|
||||||
|
memset(num, 0, 5);
|
||||||
|
memcpy(num, start, end - start);
|
||||||
|
if (!qeth_isxdigit(num))
|
||||||
|
return -EINVAL;
|
||||||
|
sscanf(start, "%x", &num2);
|
||||||
|
if (found)
|
||||||
|
in_tmp[save_cnt++] = num2;
|
||||||
|
else
|
||||||
|
in[cnt++] = num2;
|
||||||
|
if (out)
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (found)
|
||||||
|
return -EINVAL;
|
||||||
|
found = 1;
|
||||||
}
|
}
|
||||||
else {
|
start = ++end;
|
||||||
end = strchr(start, ':');
|
}
|
||||||
len = end - start;
|
cnt = 7;
|
||||||
}
|
while (save_cnt)
|
||||||
if ((len <= 0) || (len > 4))
|
in[cnt--] = in_tmp[--save_cnt];
|
||||||
return -EINVAL;
|
|
||||||
memset(abuf, 0, 5);
|
|
||||||
strncpy(abuf, start, len);
|
|
||||||
if (!qeth_isxdigit(abuf))
|
|
||||||
return -EINVAL;
|
|
||||||
tmp_addr[i] = simple_strtoul(abuf, &tmp, 16);
|
|
||||||
start = end + 1;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,8 +59,7 @@ qeth_eddp_free_context(struct qeth_eddp_context *ctx)
|
|||||||
for (i = 0; i < ctx->num_pages; ++i)
|
for (i = 0; i < ctx->num_pages; ++i)
|
||||||
free_page((unsigned long)ctx->pages[i]);
|
free_page((unsigned long)ctx->pages[i]);
|
||||||
kfree(ctx->pages);
|
kfree(ctx->pages);
|
||||||
if (ctx->elements != NULL)
|
kfree(ctx->elements);
|
||||||
kfree(ctx->elements);
|
|
||||||
kfree(ctx);
|
kfree(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,6 +412,13 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
|
|||||||
|
|
||||||
QETH_DBF_TEXT(trace, 5, "eddpftcp");
|
QETH_DBF_TEXT(trace, 5, "eddpftcp");
|
||||||
eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl;
|
eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl;
|
||||||
|
if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
|
||||||
|
eddp->skb_offset += sizeof(struct ethhdr);
|
||||||
|
#ifdef CONFIG_QETH_VLAN
|
||||||
|
if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
|
||||||
|
eddp->skb_offset += VLAN_HLEN;
|
||||||
|
#endif /* CONFIG_QETH_VLAN */
|
||||||
|
}
|
||||||
tcph = eddp->skb->h.th;
|
tcph = eddp->skb->h.th;
|
||||||
while (eddp->skb_offset < eddp->skb->len) {
|
while (eddp->skb_offset < eddp->skb->len) {
|
||||||
data_len = min((int)skb_shinfo(eddp->skb)->tso_size,
|
data_len = min((int)skb_shinfo(eddp->skb)->tso_size,
|
||||||
@ -483,6 +489,7 @@ qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
if (qhdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
|
if (qhdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
|
||||||
|
skb->mac.raw = (skb->data) + sizeof(struct qeth_hdr);
|
||||||
memcpy(&eddp->mac, eth_hdr(skb), ETH_HLEN);
|
memcpy(&eddp->mac, eth_hdr(skb), ETH_HLEN);
|
||||||
#ifdef CONFIG_QETH_VLAN
|
#ifdef CONFIG_QETH_VLAN
|
||||||
if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) {
|
if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) {
|
||||||
|
@ -516,7 +516,8 @@ __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode)
|
|||||||
QETH_DBF_TEXT(setup, 3, "setoffl");
|
QETH_DBF_TEXT(setup, 3, "setoffl");
|
||||||
QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
|
QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
|
||||||
|
|
||||||
netif_carrier_off(card->dev);
|
if (card->dev && netif_carrier_ok(card->dev))
|
||||||
|
netif_carrier_off(card->dev);
|
||||||
recover_flag = card->state;
|
recover_flag = card->state;
|
||||||
if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){
|
if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){
|
||||||
PRINT_WARN("Stopping card %s interrupted by user!\n",
|
PRINT_WARN("Stopping card %s interrupted by user!\n",
|
||||||
@ -1679,6 +1680,7 @@ qeth_cmd_timeout(unsigned long data)
|
|||||||
spin_unlock_irqrestore(&reply->card->lock, flags);
|
spin_unlock_irqrestore(&reply->card->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct qeth_ipa_cmd *
|
static struct qeth_ipa_cmd *
|
||||||
qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
|
qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
|
||||||
{
|
{
|
||||||
@ -1699,7 +1701,8 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
|
|||||||
QETH_CARD_IFNAME(card),
|
QETH_CARD_IFNAME(card),
|
||||||
card->info.chpid);
|
card->info.chpid);
|
||||||
card->lan_online = 0;
|
card->lan_online = 0;
|
||||||
netif_carrier_off(card->dev);
|
if (card->dev && netif_carrier_ok(card->dev))
|
||||||
|
netif_carrier_off(card->dev);
|
||||||
return NULL;
|
return NULL;
|
||||||
case IPA_CMD_STARTLAN:
|
case IPA_CMD_STARTLAN:
|
||||||
PRINT_INFO("Link reestablished on %s "
|
PRINT_INFO("Link reestablished on %s "
|
||||||
@ -5562,7 +5565,7 @@ qeth_set_multicast_list(struct net_device *dev)
|
|||||||
if (card->info.type == QETH_CARD_TYPE_OSN)
|
if (card->info.type == QETH_CARD_TYPE_OSN)
|
||||||
return ;
|
return ;
|
||||||
|
|
||||||
QETH_DBF_TEXT(trace,3,"setmulti");
|
QETH_DBF_TEXT(trace, 3, "setmulti");
|
||||||
qeth_delete_mc_addresses(card);
|
qeth_delete_mc_addresses(card);
|
||||||
if (card->options.layer2) {
|
if (card->options.layer2) {
|
||||||
qeth_layer2_add_multicast(card);
|
qeth_layer2_add_multicast(card);
|
||||||
@ -5579,7 +5582,6 @@ out:
|
|||||||
return;
|
return;
|
||||||
if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0)
|
if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0)
|
||||||
schedule_work(&card->kernel_thread_starter);
|
schedule_work(&card->kernel_thread_starter);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -7452,6 +7454,7 @@ qeth_softsetup_card(struct qeth_card *card)
|
|||||||
card->lan_online = 1;
|
card->lan_online = 1;
|
||||||
if (card->info.type==QETH_CARD_TYPE_OSN)
|
if (card->info.type==QETH_CARD_TYPE_OSN)
|
||||||
goto out;
|
goto out;
|
||||||
|
qeth_set_large_send(card, card->options.large_send);
|
||||||
if (card->options.layer2) {
|
if (card->options.layer2) {
|
||||||
card->dev->features |=
|
card->dev->features |=
|
||||||
NETIF_F_HW_VLAN_FILTER |
|
NETIF_F_HW_VLAN_FILTER |
|
||||||
@ -7468,12 +7471,6 @@ qeth_softsetup_card(struct qeth_card *card)
|
|||||||
#endif
|
#endif
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if ((card->options.large_send == QETH_LARGE_SEND_EDDP) ||
|
|
||||||
(card->options.large_send == QETH_LARGE_SEND_TSO))
|
|
||||||
card->dev->features |= NETIF_F_TSO | NETIF_F_SG;
|
|
||||||
else
|
|
||||||
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
|
|
||||||
|
|
||||||
if ((rc = qeth_setadapter_parms(card)))
|
if ((rc = qeth_setadapter_parms(card)))
|
||||||
QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
|
QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
|
||||||
if ((rc = qeth_start_ipassists(card)))
|
if ((rc = qeth_start_ipassists(card)))
|
||||||
|
Loading…
Reference in New Issue
Block a user