Commit e172577d authored by Frank Pavlic's avatar Frank Pavlic Committed by Jeff Garzik

[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: default avatarPeter Tiedemann <ptiedem@de.ibm.com>
Signed-off-by: default avatarFrank Pavlic <pavlic@de.ibm.com>

diffstat:
 ctcmain.c |   41 ++++++++++++++++++++++-------------------
 1 files changed, 22 insertions(+), 19 deletions(-)
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent 46a60f2d
/* /*
* $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 @@ ...@@ -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[] = { ...@@ -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 ...@@ -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[] = { ...@@ -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 ...@@ -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) ...@@ -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[] = { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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 ...@@ -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)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment