[PATCH] s390: ctc driver fixes
Jeff, sorry if I have flooded your inbox, I had some problems with the mail server here yesterday, but it seems to be fixed ... Ok patch 3-4 have no dependencies on patch 2 since only qeth driver is affected.Thus I have made a new patch 2 for ctc driver. Thank you . [patch 2/4] s390: ctc driver fixes From: Peter Tiedemann <ptiedem@de.ibm.com> - race condition fixed - minor cleanup Signed-off-by: Peter Tiedemann <ptiedem@de.ibm.com> Signed-off-by: Frank Pavlic <pavlic@de.ibm.com> diffstat: ctcmain.c | 41 ++++++++++++++++++++++------------------- 1 files changed, 22 insertions(+), 19 deletions(-) Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
This commit is contained in:
parent
46a60f2d71
commit
e172577da0
1 changed files with 22 additions and 19 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* $Id: ctcmain.c,v 1.74 2005/03/24 09:04:17 mschwide Exp $
|
* $Id: ctcmain.c,v 1.78 2005/09/07 12:18:02 pavlic Exp $
|
||||||
*
|
*
|
||||||
* CTC / ESCON network driver
|
* CTC / ESCON network driver
|
||||||
*
|
*
|
||||||
|
@ -37,10 +37,9 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*
|
*
|
||||||
* RELEASE-TAG: CTC/ESCON network driver $Revision: 1.74 $
|
* RELEASE-TAG: CTC/ESCON network driver $Revision: 1.78 $
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
@ -135,7 +134,7 @@ static const char *dev_event_names[] = {
|
||||||
"TX down",
|
"TX down",
|
||||||
"Restart",
|
"Restart",
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Events of the channel statemachine
|
* Events of the channel statemachine
|
||||||
*/
|
*/
|
||||||
|
@ -249,7 +248,7 @@ static void
|
||||||
print_banner(void)
|
print_banner(void)
|
||||||
{
|
{
|
||||||
static int printed = 0;
|
static int printed = 0;
|
||||||
char vbuf[] = "$Revision: 1.74 $";
|
char vbuf[] = "$Revision: 1.78 $";
|
||||||
char *version = vbuf;
|
char *version = vbuf;
|
||||||
|
|
||||||
if (printed)
|
if (printed)
|
||||||
|
@ -334,7 +333,7 @@ static const char *ch_state_names[] = {
|
||||||
"Restarting",
|
"Restarting",
|
||||||
"Not operational",
|
"Not operational",
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
/**
|
/**
|
||||||
* Dump header and first 16 bytes of an sk_buff for debugging purposes.
|
* Dump header and first 16 bytes of an sk_buff for debugging purposes.
|
||||||
|
@ -671,7 +670,7 @@ static void
|
||||||
fsm_action_nop(fsm_instance * fi, int event, void *arg)
|
fsm_action_nop(fsm_instance * fi, int event, void *arg)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Actions for channel - statemachines.
|
* Actions for channel - statemachines.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
@ -1514,7 +1513,6 @@ ch_action_reinit(fsm_instance *fi, int event, void *arg)
|
||||||
fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev);
|
fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The statemachine for a channel.
|
* The statemachine for a channel.
|
||||||
*/
|
*/
|
||||||
|
@ -1625,7 +1623,7 @@ static const fsm_node ch_fsm[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node);
|
static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Functions related to setup and device detection.
|
* Functions related to setup and device detection.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
@ -1976,7 +1974,7 @@ ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
|
||||||
fsm_event(ch->fsm, CH_EVENT_IRQ, ch);
|
fsm_event(ch->fsm, CH_EVENT_IRQ, ch);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Actions for interface - statemachine.
|
* Actions for interface - statemachine.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
@ -2209,13 +2207,18 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
DBF_TEXT(trace, 5, __FUNCTION__);
|
DBF_TEXT(trace, 5, __FUNCTION__);
|
||||||
|
/* we need to acquire the lock for testing the state
|
||||||
|
* otherwise we can have an IRQ changing the state to
|
||||||
|
* TXIDLE after the test but before acquiring the lock.
|
||||||
|
*/
|
||||||
|
spin_lock_irqsave(&ch->collect_lock, saveflags);
|
||||||
if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) {
|
if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) {
|
||||||
int l = skb->len + LL_HEADER_LENGTH;
|
int l = skb->len + LL_HEADER_LENGTH;
|
||||||
|
|
||||||
spin_lock_irqsave(&ch->collect_lock, saveflags);
|
if (ch->collect_len + l > ch->max_bufsize - 2) {
|
||||||
if (ch->collect_len + l > ch->max_bufsize - 2)
|
spin_unlock_irqrestore(&ch->collect_lock, saveflags);
|
||||||
rc = -EBUSY;
|
return -EBUSY;
|
||||||
else {
|
} else {
|
||||||
atomic_inc(&skb->users);
|
atomic_inc(&skb->users);
|
||||||
header.length = l;
|
header.length = l;
|
||||||
header.type = skb->protocol;
|
header.type = skb->protocol;
|
||||||
|
@ -2231,7 +2234,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
|
||||||
int ccw_idx;
|
int ccw_idx;
|
||||||
struct sk_buff *nskb;
|
struct sk_buff *nskb;
|
||||||
unsigned long hi;
|
unsigned long hi;
|
||||||
|
spin_unlock_irqrestore(&ch->collect_lock, saveflags);
|
||||||
/**
|
/**
|
||||||
* Protect skb against beeing free'd by upper
|
* Protect skb against beeing free'd by upper
|
||||||
* layers.
|
* layers.
|
||||||
|
@ -2256,6 +2259,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
|
||||||
if (!nskb) {
|
if (!nskb) {
|
||||||
atomic_dec(&skb->users);
|
atomic_dec(&skb->users);
|
||||||
skb_pull(skb, LL_HEADER_LENGTH + 2);
|
skb_pull(skb, LL_HEADER_LENGTH + 2);
|
||||||
|
ctc_clear_busy(ch->netdev);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
} else {
|
} else {
|
||||||
memcpy(skb_put(nskb, skb->len),
|
memcpy(skb_put(nskb, skb->len),
|
||||||
|
@ -2281,6 +2285,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
|
||||||
*/
|
*/
|
||||||
atomic_dec(&skb->users);
|
atomic_dec(&skb->users);
|
||||||
skb_pull(skb, LL_HEADER_LENGTH + 2);
|
skb_pull(skb, LL_HEADER_LENGTH + 2);
|
||||||
|
ctc_clear_busy(ch->netdev);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2327,9 +2332,10 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctc_clear_busy(ch->netdev);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface API for upper network layers
|
* Interface API for upper network layers
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
@ -2421,7 +2427,6 @@ ctc_tx(struct sk_buff *skb, struct net_device * dev)
|
||||||
dev->trans_start = jiffies;
|
dev->trans_start = jiffies;
|
||||||
if (transmit_skb(privptr->channel[WRITE], skb) != 0)
|
if (transmit_skb(privptr->channel[WRITE], skb) != 0)
|
||||||
rc = 1;
|
rc = 1;
|
||||||
ctc_clear_busy(dev);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2610,7 +2615,6 @@ stats_write(struct device *dev, struct device_attribute *attr, const char *buf,
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ctc_netdev_unregister(struct net_device * dev)
|
ctc_netdev_unregister(struct net_device * dev)
|
||||||
{
|
{
|
||||||
|
@ -2685,7 +2689,6 @@ ctc_proto_store(struct device *dev, struct device_attribute *attr, const char *b
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
ctc_type_show(struct device *dev, struct device_attribute *attr, char *buf)
|
ctc_type_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue