diff options
| -rw-r--r-- | drivers/s390/net/ctcmain.c | 41 |
1 files changed, 22 insertions, 19 deletions
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index 96ca863eaff2..0db4f57a6a95 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * $Id: ctcmain.c,v 1.74 2005/03/24 09:04:17 mschwide Exp $ | 2 | * $Id: ctcmain.c,v 1.78 2005/09/07 12:18:02 pavlic Exp $ |
| 3 | * | 3 | * |
| 4 | * CTC / ESCON network driver | 4 | * CTC / ESCON network driver |
| 5 | * | 5 | * |
| @@ -37,10 +37,9 @@ | |||
| 37 | * along with this program; if not, write to the Free Software | 37 | * along with this program; if not, write to the Free Software |
| 38 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 38 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 39 | * | 39 | * |
| 40 | * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.74 $ | 40 | * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.78 $ |
| 41 | * | 41 | * |
| 42 | */ | 42 | */ |
| 43 | |||
| 44 | #undef DEBUG | 43 | #undef DEBUG |
| 45 | #include <linux/module.h> | 44 | #include <linux/module.h> |
| 46 | #include <linux/init.h> | 45 | #include <linux/init.h> |
| @@ -135,7 +134,7 @@ static const char *dev_event_names[] = { | |||
| 135 | "TX down", | 134 | "TX down", |
| 136 | "Restart", | 135 | "Restart", |
| 137 | }; | 136 | }; |
| 138 | 137 | ||
| 139 | /** | 138 | /** |
| 140 | * Events of the channel statemachine | 139 | * Events of the channel statemachine |
| 141 | */ | 140 | */ |
| @@ -249,7 +248,7 @@ static void | |||
| 249 | print_banner(void) | 248 | print_banner(void) |
| 250 | { | 249 | { |
| 251 | static int printed = 0; | 250 | static int printed = 0; |
| 252 | char vbuf[] = "$Revision: 1.74 $"; | 251 | char vbuf[] = "$Revision: 1.78 $"; |
| 253 | char *version = vbuf; | 252 | char *version = vbuf; |
| 254 | 253 | ||
| 255 | if (printed) | 254 | if (printed) |
| @@ -334,7 +333,7 @@ static const char *ch_state_names[] = { | |||
| 334 | "Restarting", | 333 | "Restarting", |
| 335 | "Not operational", | 334 | "Not operational", |
| 336 | }; | 335 | }; |
| 337 | 336 | ||
| 338 | #ifdef DEBUG | 337 | #ifdef DEBUG |
| 339 | /** | 338 | /** |
| 340 | * Dump header and first 16 bytes of an sk_buff for debugging purposes. | 339 | * Dump header and first 16 bytes of an sk_buff for debugging purposes. |
| @@ -671,7 +670,7 @@ static void | |||
| 671 | fsm_action_nop(fsm_instance * fi, int event, void *arg) | 670 | fsm_action_nop(fsm_instance * fi, int event, void *arg) |
| 672 | { | 671 | { |
| 673 | } | 672 | } |
| 674 | 673 | ||
| 675 | /** | 674 | /** |
| 676 | * Actions for channel - statemachines. | 675 | * Actions for channel - statemachines. |
| 677 | *****************************************************************************/ | 676 | *****************************************************************************/ |
| @@ -1514,7 +1513,6 @@ ch_action_reinit(fsm_instance *fi, int event, void *arg) | |||
| 1514 | fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev); | 1513 | fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev); |
| 1515 | } | 1514 | } |
| 1516 | 1515 | ||
| 1517 | |||
| 1518 | /** | 1516 | /** |
| 1519 | * The statemachine for a channel. | 1517 | * The statemachine for a channel. |
| 1520 | */ | 1518 | */ |
| @@ -1625,7 +1623,7 @@ static const fsm_node ch_fsm[] = { | |||
| 1625 | }; | 1623 | }; |
| 1626 | 1624 | ||
| 1627 | static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node); | 1625 | static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node); |
| 1628 | 1626 | ||
| 1629 | /** | 1627 | /** |
| 1630 | * Functions related to setup and device detection. | 1628 | * Functions related to setup and device detection. |
| 1631 | *****************************************************************************/ | 1629 | *****************************************************************************/ |
| @@ -1976,7 +1974,7 @@ ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
| 1976 | fsm_event(ch->fsm, CH_EVENT_IRQ, ch); | 1974 | fsm_event(ch->fsm, CH_EVENT_IRQ, ch); |
| 1977 | 1975 | ||
| 1978 | } | 1976 | } |
| 1979 | 1977 | ||
| 1980 | /** | 1978 | /** |
| 1981 | * Actions for interface - statemachine. | 1979 | * Actions for interface - statemachine. |
| 1982 | *****************************************************************************/ | 1980 | *****************************************************************************/ |
| @@ -2209,13 +2207,18 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
| 2209 | int rc = 0; | 2207 | int rc = 0; |
| 2210 | 2208 | ||
| 2211 | DBF_TEXT(trace, 5, __FUNCTION__); | 2209 | DBF_TEXT(trace, 5, __FUNCTION__); |
| 2210 | /* we need to acquire the lock for testing the state | ||
| 2211 | * otherwise we can have an IRQ changing the state to | ||
| 2212 | * TXIDLE after the test but before acquiring the lock. | ||
| 2213 | */ | ||
| 2214 | spin_lock_irqsave(&ch->collect_lock, saveflags); | ||
| 2212 | if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) { | 2215 | if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) { |
| 2213 | int l = skb->len + LL_HEADER_LENGTH; | 2216 | int l = skb->len + LL_HEADER_LENGTH; |
| 2214 | 2217 | ||
| 2215 | spin_lock_irqsave(&ch->collect_lock, saveflags); | 2218 | if (ch->collect_len + l > ch->max_bufsize - 2) { |
| 2216 | if (ch->collect_len + l > ch->max_bufsize - 2) | 2219 | spin_unlock_irqrestore(&ch->collect_lock, saveflags); |
| 2217 | rc = -EBUSY; | 2220 | return -EBUSY; |
| 2218 | else { | 2221 | } else { |
| 2219 | atomic_inc(&skb->users); | 2222 | atomic_inc(&skb->users); |
| 2220 | header.length = l; | 2223 | header.length = l; |
| 2221 | header.type = skb->protocol; | 2224 | header.type = skb->protocol; |
| @@ -2231,7 +2234,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
| 2231 | int ccw_idx; | 2234 | int ccw_idx; |
| 2232 | struct sk_buff *nskb; | 2235 | struct sk_buff *nskb; |
| 2233 | unsigned long hi; | 2236 | unsigned long hi; |
| 2234 | 2237 | spin_unlock_irqrestore(&ch->collect_lock, saveflags); | |
| 2235 | /** | 2238 | /** |
| 2236 | * Protect skb against beeing free'd by upper | 2239 | * Protect skb against beeing free'd by upper |
| 2237 | * layers. | 2240 | * layers. |
| @@ -2256,6 +2259,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
| 2256 | if (!nskb) { | 2259 | if (!nskb) { |
| 2257 | atomic_dec(&skb->users); | 2260 | atomic_dec(&skb->users); |
| 2258 | skb_pull(skb, LL_HEADER_LENGTH + 2); | 2261 | skb_pull(skb, LL_HEADER_LENGTH + 2); |
| 2262 | ctc_clear_busy(ch->netdev); | ||
| 2259 | return -ENOMEM; | 2263 | return -ENOMEM; |
| 2260 | } else { | 2264 | } else { |
| 2261 | memcpy(skb_put(nskb, skb->len), | 2265 | memcpy(skb_put(nskb, skb->len), |
| @@ -2281,6 +2285,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
| 2281 | */ | 2285 | */ |
| 2282 | atomic_dec(&skb->users); | 2286 | atomic_dec(&skb->users); |
| 2283 | skb_pull(skb, LL_HEADER_LENGTH + 2); | 2287 | skb_pull(skb, LL_HEADER_LENGTH + 2); |
| 2288 | ctc_clear_busy(ch->netdev); | ||
| 2284 | return -EBUSY; | 2289 | return -EBUSY; |
| 2285 | } | 2290 | } |
| 2286 | 2291 | ||
| @@ -2327,9 +2332,10 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
| 2327 | } | 2332 | } |
| 2328 | } | 2333 | } |
| 2329 | 2334 | ||
| 2335 | ctc_clear_busy(ch->netdev); | ||
| 2330 | return rc; | 2336 | return rc; |
| 2331 | } | 2337 | } |
| 2332 | 2338 | ||
| 2333 | /** | 2339 | /** |
| 2334 | * Interface API for upper network layers | 2340 | * Interface API for upper network layers |
| 2335 | *****************************************************************************/ | 2341 | *****************************************************************************/ |
| @@ -2421,7 +2427,6 @@ ctc_tx(struct sk_buff *skb, struct net_device * dev) | |||
| 2421 | dev->trans_start = jiffies; | 2427 | dev->trans_start = jiffies; |
| 2422 | if (transmit_skb(privptr->channel[WRITE], skb) != 0) | 2428 | if (transmit_skb(privptr->channel[WRITE], skb) != 0) |
| 2423 | rc = 1; | 2429 | rc = 1; |
| 2424 | ctc_clear_busy(dev); | ||
| 2425 | return rc; | 2430 | return rc; |
| 2426 | } | 2431 | } |
| 2427 | 2432 | ||
| @@ -2610,7 +2615,6 @@ stats_write(struct device *dev, struct device_attribute *attr, const char *buf, | |||
| 2610 | return count; | 2615 | return count; |
| 2611 | } | 2616 | } |
| 2612 | 2617 | ||
| 2613 | |||
| 2614 | static void | 2618 | static void |
| 2615 | ctc_netdev_unregister(struct net_device * dev) | 2619 | ctc_netdev_unregister(struct net_device * dev) |
| 2616 | { | 2620 | { |
| @@ -2685,7 +2689,6 @@ ctc_proto_store(struct device *dev, struct device_attribute *attr, const char *b | |||
| 2685 | return count; | 2689 | return count; |
| 2686 | } | 2690 | } |
| 2687 | 2691 | ||
| 2688 | |||
| 2689 | static ssize_t | 2692 | static ssize_t |
| 2690 | ctc_type_show(struct device *dev, struct device_attribute *attr, char *buf) | 2693 | ctc_type_show(struct device *dev, struct device_attribute *attr, char *buf) |
| 2691 | { | 2694 | { |
