/*
*
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.130 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.145 $)
*
* Linux on zSeries OSA Express and HiperSockets support
*
* Frank Pavlic (pavlic@de.ibm.com) and
* Thomas Spatzier <tspat@de.ibm.com>
*
- * $Revision: 1.130 $ $Date: 2004/08/05 11:21:50 $
+ * $Revision: 1.145 $ $Date: 2004/10/08 15:08:40 $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <linux/reboot.h>
#include <asm/qeth.h>
#include <linux/mii.h>
+#include <linux/rcupdate.h>
#include "qeth.h"
#include "qeth_mpc.h"
#include "qeth_fs.h"
-#define VERSION_QETH_C "$Revision: 1.130 $"
+#define VERSION_QETH_C "$Revision: 1.145 $"
static const char *version = "qeth S/390 OSA-Express driver";
/**
skb->mac.raw = skb->data;
skb_pull(skb, ETH_ALEN * 2 + sizeof (short));
- eth = skb->mac.ethernet;
+ eth = eth_hdr(skb);
if (*eth->h_dest & 1) {
if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
/* return EBUSY because we sent old packet, not
* the current one */
rc = -EBUSY;
+ atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
goto out;
}
}
/* skip 4 bytes (data_len struct member) to get req_len */
if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int)))
return -EFAULT;
- ureq = kmalloc(req_len, GFP_KERNEL);
+ ureq = kmalloc(req_len+sizeof(struct qeth_snmp_ureq_hdr), GFP_KERNEL);
if (!ureq) {
QETH_DBF_TEXT(trace, 2, "snmpnome");
return -ENOMEM;
}
- if (copy_from_user(ureq, udata, req_len)){
+ if (copy_from_user(ureq, udata,
+ req_len+sizeof(struct qeth_snmp_ureq_hdr))){
kfree(ureq);
return -EFAULT;
}
if (!card)
return -ENODEV;
- if (card->state != CARD_STATE_UP)
+ if ((card->state != CARD_STATE_UP) &&
+ (card->state != CARD_STATE_SOFTSETUP))
return -ENODEV;
switch (cmd){
QETH_DBF_TEXT(trace, 4, "frvaddr4");
if (!card->vlangrp)
return;
- in_dev = in_dev_get(card->vlangrp->vlan_devices[vid]);
+ rcu_read_lock();
+ in_dev = __in_dev_get(card->vlangrp->vlan_devices[vid]);
if (!in_dev)
- return;
+ goto out;
for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next){
addr = qeth_get_addr_buffer(QETH_PROT_IPV4);
if (addr){
kfree(addr);
}
}
- in_dev_put(in_dev);
+out:
+ rcu_read_unlock();
}
static void
in_dev = in_dev_get(vg->vlan_devices[i]);
if (!in_dev)
continue;
- read_lock(&in_dev->lock);
+ read_lock(&in_dev->mc_list_lock);
qeth_add_mc(card,in_dev);
- read_unlock(&in_dev->lock);
+ read_unlock(&in_dev->mc_list_lock);
in_dev_put(in_dev);
}
#endif
in4_dev = in_dev_get(card->dev);
if (in4_dev == NULL)
return;
- read_lock(&in4_dev->lock);
+ read_lock(&in4_dev->mc_list_lock);
qeth_add_mc(card, in4_dev);
qeth_add_vlan_mc(card);
- read_unlock(&in4_dev->lock);
+ read_unlock(&in4_dev->mc_list_lock);
in_dev_put(in4_dev);
}
QETH_DBF_TEXT(trace,3,"ipaipfrg");
if (!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) {
- PRINT_INFO("IP fragmentation not supported on %s\n",
+ PRINT_INFO("Hardware IP fragmentation not supported on %s\n",
card->info.if_name);
return -EOPNOTSUPP;
}
rc = qeth_send_simple_setassparms(card, IPA_IP_FRAGMENTATION,
IPA_CMD_ASS_START, 0);
if (rc) {
- PRINT_WARN("Could not start IP fragmentation "
+ PRINT_WARN("Could not start Hardware IP fragmentation "
"assist on %s: 0x%x\n",
card->info.if_name, rc);
} else
- PRINT_INFO("IP fragmentation enabled \n");
+ PRINT_INFO("Hardware IP fragmentation enabled \n");
return rc;
}
qeth_arp_constructor(struct neighbour *neigh)
{
struct net_device *dev = neigh->dev;
- struct in_device *in_dev = in_dev_get(dev);
+ struct in_device *in_dev;
+ struct neigh_parms *parms;
- if (in_dev == NULL)
- return -EINVAL;
if (!qeth_verify_dev(dev)) {
- in_dev_put(in_dev);
return qeth_old_arp_constructor(neigh);
}
+ rcu_read_lock();
+ in_dev = rcu_dereference(__in_dev_get(dev));
+ if (in_dev == NULL) {
+ rcu_read_unlock();
+ return -EINVAL;
+ }
+
+ parms = in_dev->arp_parms;
+ __neigh_parms_put(neigh->parms);
+ neigh->parms = neigh_parms_clone(parms);
+ rcu_read_unlock();
+
neigh->type = inet_addr_type(*(u32 *) neigh->primary_key);
- if (in_dev->arp_parms)
- neigh->parms = in_dev->arp_parms;
- in_dev_put(in_dev);
neigh->nud_state = NUD_NOARP;
neigh->ops = arp_direct_ops;
neigh->output = neigh->ops->queue_xmit;