diff options
Diffstat (limited to 'drivers/s390/net/ctcm_main.c')
-rw-r--r-- | drivers/s390/net/ctcm_main.c | 514 |
1 files changed, 238 insertions, 276 deletions
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 6b13c1c1beb8..126a3ebb8ab2 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c | |||
@@ -84,20 +84,19 @@ void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb) | |||
84 | skb_pull(pskb, LL_HEADER_LENGTH); | 84 | skb_pull(pskb, LL_HEADER_LENGTH); |
85 | if ((ch->protocol == CTCM_PROTO_S390) && | 85 | if ((ch->protocol == CTCM_PROTO_S390) && |
86 | (header->type != ETH_P_IP)) { | 86 | (header->type != ETH_P_IP)) { |
87 | |||
88 | if (!(ch->logflags & LOG_FLAG_ILLEGALPKT)) { | 87 | if (!(ch->logflags & LOG_FLAG_ILLEGALPKT)) { |
88 | ch->logflags |= LOG_FLAG_ILLEGALPKT; | ||
89 | /* | 89 | /* |
90 | * Check packet type only if we stick strictly | 90 | * Check packet type only if we stick strictly |
91 | * to S/390's protocol of OS390. This only | 91 | * to S/390's protocol of OS390. This only |
92 | * supports IP. Otherwise allow any packet | 92 | * supports IP. Otherwise allow any packet |
93 | * type. | 93 | * type. |
94 | */ | 94 | */ |
95 | ctcm_pr_warn("%s Illegal packet type 0x%04x " | 95 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR, |
96 | "received, dropping\n", | 96 | "%s(%s): Illegal packet type 0x%04x" |
97 | dev->name, header->type); | 97 | " - dropping", |
98 | ch->logflags |= LOG_FLAG_ILLEGALPKT; | 98 | CTCM_FUNTAIL, dev->name, header->type); |
99 | } | 99 | } |
100 | |||
101 | priv->stats.rx_dropped++; | 100 | priv->stats.rx_dropped++; |
102 | priv->stats.rx_frame_errors++; | 101 | priv->stats.rx_frame_errors++; |
103 | return; | 102 | return; |
@@ -105,11 +104,11 @@ void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb) | |||
105 | pskb->protocol = ntohs(header->type); | 104 | pskb->protocol = ntohs(header->type); |
106 | if (header->length <= LL_HEADER_LENGTH) { | 105 | if (header->length <= LL_HEADER_LENGTH) { |
107 | if (!(ch->logflags & LOG_FLAG_ILLEGALSIZE)) { | 106 | if (!(ch->logflags & LOG_FLAG_ILLEGALSIZE)) { |
108 | ctcm_pr_warn( | 107 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR, |
109 | "%s Illegal packet size %d " | 108 | "%s(%s): Illegal packet size %d(%d,%d)" |
110 | "received (MTU=%d blocklen=%d), " | 109 | "- dropping", |
111 | "dropping\n", dev->name, header->length, | 110 | CTCM_FUNTAIL, dev->name, |
112 | dev->mtu, len); | 111 | header->length, dev->mtu, len); |
113 | ch->logflags |= LOG_FLAG_ILLEGALSIZE; | 112 | ch->logflags |= LOG_FLAG_ILLEGALSIZE; |
114 | } | 113 | } |
115 | 114 | ||
@@ -122,10 +121,10 @@ void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb) | |||
122 | if ((header->length > skb_tailroom(pskb)) || | 121 | if ((header->length > skb_tailroom(pskb)) || |
123 | (header->length > len)) { | 122 | (header->length > len)) { |
124 | if (!(ch->logflags & LOG_FLAG_OVERRUN)) { | 123 | if (!(ch->logflags & LOG_FLAG_OVERRUN)) { |
125 | ctcm_pr_warn( | 124 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR, |
126 | "%s Illegal packet size %d (beyond the" | 125 | "%s(%s): Packet size %d (overrun)" |
127 | " end of received data), dropping\n", | 126 | " - dropping", CTCM_FUNTAIL, |
128 | dev->name, header->length); | 127 | dev->name, header->length); |
129 | ch->logflags |= LOG_FLAG_OVERRUN; | 128 | ch->logflags |= LOG_FLAG_OVERRUN; |
130 | } | 129 | } |
131 | 130 | ||
@@ -139,9 +138,9 @@ void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb) | |||
139 | skb = dev_alloc_skb(pskb->len); | 138 | skb = dev_alloc_skb(pskb->len); |
140 | if (!skb) { | 139 | if (!skb) { |
141 | if (!(ch->logflags & LOG_FLAG_NOMEM)) { | 140 | if (!(ch->logflags & LOG_FLAG_NOMEM)) { |
142 | ctcm_pr_warn( | 141 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR, |
143 | "%s Out of memory in ctcm_unpack_skb\n", | 142 | "%s(%s): MEMORY allocation error", |
144 | dev->name); | 143 | CTCM_FUNTAIL, dev->name); |
145 | ch->logflags |= LOG_FLAG_NOMEM; | 144 | ch->logflags |= LOG_FLAG_NOMEM; |
146 | } | 145 | } |
147 | priv->stats.rx_dropped++; | 146 | priv->stats.rx_dropped++; |
@@ -184,7 +183,7 @@ void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb) | |||
184 | */ | 183 | */ |
185 | static void channel_free(struct channel *ch) | 184 | static void channel_free(struct channel *ch) |
186 | { | 185 | { |
187 | CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__); | 186 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s(%s)", CTCM_FUNTAIL, ch->id); |
188 | ch->flags &= ~CHANNEL_FLAGS_INUSE; | 187 | ch->flags &= ~CHANNEL_FLAGS_INUSE; |
189 | fsm_newstate(ch->fsm, CTC_STATE_IDLE); | 188 | fsm_newstate(ch->fsm, CTC_STATE_IDLE); |
190 | } | 189 | } |
@@ -251,19 +250,12 @@ static struct channel *channel_get(enum channel_types type, | |||
251 | { | 250 | { |
252 | struct channel *ch = channels; | 251 | struct channel *ch = channels; |
253 | 252 | ||
254 | if (do_debug) { | ||
255 | char buf[64]; | ||
256 | sprintf(buf, "%s(%d, %s, %d)\n", | ||
257 | CTCM_FUNTAIL, type, id, direction); | ||
258 | CTCM_DBF_TEXT(TRACE, CTC_DBF_INFO, buf); | ||
259 | } | ||
260 | while (ch && (strncmp(ch->id, id, CTCM_ID_SIZE) || (ch->type != type))) | 253 | while (ch && (strncmp(ch->id, id, CTCM_ID_SIZE) || (ch->type != type))) |
261 | ch = ch->next; | 254 | ch = ch->next; |
262 | if (!ch) { | 255 | if (!ch) { |
263 | char buf[64]; | 256 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR, |
264 | sprintf(buf, "%s(%d, %s, %d) not found in channel list\n", | 257 | "%s(%d, %s, %d) not found in channel list\n", |
265 | CTCM_FUNTAIL, type, id, direction); | 258 | CTCM_FUNTAIL, type, id, direction); |
266 | CTCM_DBF_TEXT(ERROR, CTC_DBF_ERROR, buf); | ||
267 | } else { | 259 | } else { |
268 | if (ch->flags & CHANNEL_FLAGS_INUSE) | 260 | if (ch->flags & CHANNEL_FLAGS_INUSE) |
269 | ch = NULL; | 261 | ch = NULL; |
@@ -283,8 +275,9 @@ static long ctcm_check_irb_error(struct ccw_device *cdev, struct irb *irb) | |||
283 | if (!IS_ERR(irb)) | 275 | if (!IS_ERR(irb)) |
284 | return 0; | 276 | return 0; |
285 | 277 | ||
286 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_WARN, "irb error %ld on device %s\n", | 278 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_WARN, |
287 | PTR_ERR(irb), cdev->dev.bus_id); | 279 | "irb error %ld on device %s\n", |
280 | PTR_ERR(irb), cdev->dev.bus_id); | ||
288 | 281 | ||
289 | switch (PTR_ERR(irb)) { | 282 | switch (PTR_ERR(irb)) { |
290 | case -EIO: | 283 | case -EIO: |
@@ -307,58 +300,85 @@ static long ctcm_check_irb_error(struct ccw_device *cdev, struct irb *irb) | |||
307 | * ch The channel, the sense code belongs to. | 300 | * ch The channel, the sense code belongs to. |
308 | * sense The sense code to inspect. | 301 | * sense The sense code to inspect. |
309 | */ | 302 | */ |
310 | static inline void ccw_unit_check(struct channel *ch, unsigned char sense) | 303 | static inline void ccw_unit_check(struct channel *ch, __u8 sense) |
311 | { | 304 | { |
312 | CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__); | 305 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, |
306 | "%s(%s): %02x", | ||
307 | CTCM_FUNTAIL, ch->id, sense); | ||
308 | |||
313 | if (sense & SNS0_INTERVENTION_REQ) { | 309 | if (sense & SNS0_INTERVENTION_REQ) { |
314 | if (sense & 0x01) { | 310 | if (sense & 0x01) { |
315 | ctcm_pr_debug("%s: Interface disc. or Sel. reset " | 311 | if (ch->sense_rc != 0x01) { |
316 | "(remote)\n", ch->id); | 312 | ctcm_pr_debug("%s: Interface disc. or Sel. " |
313 | "reset (remote)\n", ch->id); | ||
314 | ch->sense_rc = 0x01; | ||
315 | } | ||
317 | fsm_event(ch->fsm, CTC_EVENT_UC_RCRESET, ch); | 316 | fsm_event(ch->fsm, CTC_EVENT_UC_RCRESET, ch); |
318 | } else { | 317 | } else { |
319 | ctcm_pr_debug("%s: System reset (remote)\n", ch->id); | 318 | if (ch->sense_rc != SNS0_INTERVENTION_REQ) { |
319 | ctcm_pr_debug("%s: System reset (remote)\n", | ||
320 | ch->id); | ||
321 | ch->sense_rc = SNS0_INTERVENTION_REQ; | ||
322 | } | ||
320 | fsm_event(ch->fsm, CTC_EVENT_UC_RSRESET, ch); | 323 | fsm_event(ch->fsm, CTC_EVENT_UC_RSRESET, ch); |
321 | } | 324 | } |
322 | } else if (sense & SNS0_EQUIPMENT_CHECK) { | 325 | } else if (sense & SNS0_EQUIPMENT_CHECK) { |
323 | if (sense & SNS0_BUS_OUT_CHECK) { | 326 | if (sense & SNS0_BUS_OUT_CHECK) { |
324 | ctcm_pr_warn("%s: Hardware malfunction (remote)\n", | 327 | if (ch->sense_rc != SNS0_BUS_OUT_CHECK) { |
325 | ch->id); | 328 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN, |
329 | "%s(%s): remote HW error %02x", | ||
330 | CTCM_FUNTAIL, ch->id, sense); | ||
331 | ch->sense_rc = SNS0_BUS_OUT_CHECK; | ||
332 | } | ||
326 | fsm_event(ch->fsm, CTC_EVENT_UC_HWFAIL, ch); | 333 | fsm_event(ch->fsm, CTC_EVENT_UC_HWFAIL, ch); |
327 | } else { | 334 | } else { |
328 | ctcm_pr_warn("%s: Read-data parity error (remote)\n", | 335 | if (ch->sense_rc != SNS0_EQUIPMENT_CHECK) { |
329 | ch->id); | 336 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN, |
337 | "%s(%s): remote read parity error %02x", | ||
338 | CTCM_FUNTAIL, ch->id, sense); | ||
339 | ch->sense_rc = SNS0_EQUIPMENT_CHECK; | ||
340 | } | ||
330 | fsm_event(ch->fsm, CTC_EVENT_UC_RXPARITY, ch); | 341 | fsm_event(ch->fsm, CTC_EVENT_UC_RXPARITY, ch); |
331 | } | 342 | } |
332 | } else if (sense & SNS0_BUS_OUT_CHECK) { | 343 | } else if (sense & SNS0_BUS_OUT_CHECK) { |
333 | if (sense & 0x04) { | 344 | if (ch->sense_rc != SNS0_BUS_OUT_CHECK) { |
334 | ctcm_pr_warn("%s: Data-streaming timeout)\n", ch->id); | 345 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN, |
346 | "%s(%s): BUS OUT error %02x", | ||
347 | CTCM_FUNTAIL, ch->id, sense); | ||
348 | ch->sense_rc = SNS0_BUS_OUT_CHECK; | ||
349 | } | ||
350 | if (sense & 0x04) /* data-streaming timeout */ | ||
335 | fsm_event(ch->fsm, CTC_EVENT_UC_TXTIMEOUT, ch); | 351 | fsm_event(ch->fsm, CTC_EVENT_UC_TXTIMEOUT, ch); |
336 | } else { | 352 | else /* Data-transfer parity error */ |
337 | ctcm_pr_warn("%s: Data-transfer parity error\n", | ||
338 | ch->id); | ||
339 | fsm_event(ch->fsm, CTC_EVENT_UC_TXPARITY, ch); | 353 | fsm_event(ch->fsm, CTC_EVENT_UC_TXPARITY, ch); |
340 | } | ||
341 | } else if (sense & SNS0_CMD_REJECT) { | 354 | } else if (sense & SNS0_CMD_REJECT) { |
342 | ctcm_pr_warn("%s: Command reject\n", ch->id); | 355 | if (ch->sense_rc != SNS0_CMD_REJECT) { |
356 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN, | ||
357 | "%s(%s): Command rejected", | ||
358 | CTCM_FUNTAIL, ch->id); | ||
359 | ch->sense_rc = SNS0_CMD_REJECT; | ||
360 | } | ||
343 | } else if (sense == 0) { | 361 | } else if (sense == 0) { |
344 | ctcm_pr_debug("%s: Unit check ZERO\n", ch->id); | 362 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN, |
363 | "%s(%s): Unit check ZERO", | ||
364 | CTCM_FUNTAIL, ch->id); | ||
345 | fsm_event(ch->fsm, CTC_EVENT_UC_ZERO, ch); | 365 | fsm_event(ch->fsm, CTC_EVENT_UC_ZERO, ch); |
346 | } else { | 366 | } else { |
347 | ctcm_pr_warn("%s: Unit Check with sense code: %02x\n", | 367 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN, |
348 | ch->id, sense); | 368 | "%s(%s): Unit check code %02x unknown", |
369 | CTCM_FUNTAIL, ch->id, sense); | ||
349 | fsm_event(ch->fsm, CTC_EVENT_UC_UNKNOWN, ch); | 370 | fsm_event(ch->fsm, CTC_EVENT_UC_UNKNOWN, ch); |
350 | } | 371 | } |
351 | } | 372 | } |
352 | 373 | ||
353 | int ctcm_ch_alloc_buffer(struct channel *ch) | 374 | int ctcm_ch_alloc_buffer(struct channel *ch) |
354 | { | 375 | { |
355 | CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__); | ||
356 | |||
357 | clear_normalized_cda(&ch->ccw[1]); | 376 | clear_normalized_cda(&ch->ccw[1]); |
358 | ch->trans_skb = __dev_alloc_skb(ch->max_bufsize, GFP_ATOMIC | GFP_DMA); | 377 | ch->trans_skb = __dev_alloc_skb(ch->max_bufsize, GFP_ATOMIC | GFP_DMA); |
359 | if (ch->trans_skb == NULL) { | 378 | if (ch->trans_skb == NULL) { |
360 | ctcm_pr_warn("%s: Couldn't alloc %s trans_skb\n", | 379 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR, |
361 | ch->id, | 380 | "%s(%s): %s trans_skb allocation error", |
381 | CTCM_FUNTAIL, ch->id, | ||
362 | (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX"); | 382 | (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX"); |
363 | return -ENOMEM; | 383 | return -ENOMEM; |
364 | } | 384 | } |
@@ -367,9 +387,9 @@ int ctcm_ch_alloc_buffer(struct channel *ch) | |||
367 | if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) { | 387 | if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) { |
368 | dev_kfree_skb(ch->trans_skb); | 388 | dev_kfree_skb(ch->trans_skb); |
369 | ch->trans_skb = NULL; | 389 | ch->trans_skb = NULL; |
370 | ctcm_pr_warn("%s: set_normalized_cda for %s " | 390 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR, |
371 | "trans_skb failed, dropping packets\n", | 391 | "%s(%s): %s set norm_cda failed", |
372 | ch->id, | 392 | CTCM_FUNTAIL, ch->id, |
373 | (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX"); | 393 | (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX"); |
374 | return -ENOMEM; | 394 | return -ENOMEM; |
375 | } | 395 | } |
@@ -516,7 +536,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
516 | atomic_dec(&skb->users); | 536 | atomic_dec(&skb->users); |
517 | skb_pull(skb, LL_HEADER_LENGTH + 2); | 537 | skb_pull(skb, LL_HEADER_LENGTH + 2); |
518 | ctcm_clear_busy(ch->netdev); | 538 | ctcm_clear_busy(ch->netdev); |
519 | return -EBUSY; | 539 | return -ENOMEM; |
520 | } | 540 | } |
521 | 541 | ||
522 | skb_reset_tail_pointer(ch->trans_skb); | 542 | skb_reset_tail_pointer(ch->trans_skb); |
@@ -570,15 +590,12 @@ static void ctcmpc_send_sweep_req(struct channel *rch) | |||
570 | struct th_sweep *header; | 590 | struct th_sweep *header; |
571 | struct sk_buff *sweep_skb; | 591 | struct sk_buff *sweep_skb; |
572 | struct channel *ch; | 592 | struct channel *ch; |
573 | int rc = 0; | 593 | /* int rc = 0; */ |
574 | 594 | ||
575 | priv = dev->priv; | 595 | priv = dev->priv; |
576 | grp = priv->mpcg; | 596 | grp = priv->mpcg; |
577 | ch = priv->channel[WRITE]; | 597 | ch = priv->channel[WRITE]; |
578 | 598 | ||
579 | if (do_debug) | ||
580 | MPC_DBF_DEV_NAME(TRACE, dev, ch->id); | ||
581 | |||
582 | /* sweep processing is not complete until response and request */ | 599 | /* sweep processing is not complete until response and request */ |
583 | /* has completed for all read channels in group */ | 600 | /* has completed for all read channels in group */ |
584 | if (grp->in_sweep == 0) { | 601 | if (grp->in_sweep == 0) { |
@@ -590,17 +607,16 @@ static void ctcmpc_send_sweep_req(struct channel *rch) | |||
590 | sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC|GFP_DMA); | 607 | sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC|GFP_DMA); |
591 | 608 | ||
592 | if (sweep_skb == NULL) { | 609 | if (sweep_skb == NULL) { |
593 | printk(KERN_INFO "Couldn't alloc sweep_skb\n"); | 610 | /* rc = -ENOMEM; */ |
594 | rc = -ENOMEM; | 611 | goto nomem; |
595 | goto done; | ||
596 | } | 612 | } |
597 | 613 | ||
598 | header = kmalloc(TH_SWEEP_LENGTH, gfp_type()); | 614 | header = kmalloc(TH_SWEEP_LENGTH, gfp_type()); |
599 | 615 | ||
600 | if (!header) { | 616 | if (!header) { |
601 | dev_kfree_skb_any(sweep_skb); | 617 | dev_kfree_skb_any(sweep_skb); |
602 | rc = -ENOMEM; | 618 | /* rc = -ENOMEM; */ |
603 | goto done; | 619 | goto nomem; |
604 | } | 620 | } |
605 | 621 | ||
606 | header->th.th_seg = 0x00 ; | 622 | header->th.th_seg = 0x00 ; |
@@ -621,12 +637,10 @@ static void ctcmpc_send_sweep_req(struct channel *rch) | |||
621 | 637 | ||
622 | return; | 638 | return; |
623 | 639 | ||
624 | done: | 640 | nomem: |
625 | if (rc != 0) { | 641 | grp->in_sweep = 0; |
626 | grp->in_sweep = 0; | 642 | ctcm_clear_busy(dev); |
627 | ctcm_clear_busy(dev); | 643 | fsm_event(grp->fsm, MPCG_EVENT_INOP, dev); |
628 | fsm_event(grp->fsm, MPCG_EVENT_INOP, dev); | ||
629 | } | ||
630 | 644 | ||
631 | return; | 645 | return; |
632 | } | 646 | } |
@@ -648,11 +662,9 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
648 | unsigned long saveflags = 0; /* avoids compiler warning */ | 662 | unsigned long saveflags = 0; /* avoids compiler warning */ |
649 | __u16 block_len; | 663 | __u16 block_len; |
650 | 664 | ||
651 | if (do_debug) | 665 | CTCM_PR_DEBUG("Enter %s: %s, cp=%i ch=0x%p id=%s state=%s\n", |
652 | ctcm_pr_debug( | 666 | __func__, dev->name, smp_processor_id(), ch, |
653 | "ctcm enter: %s(): %s cp=%i ch=0x%p id=%s state=%s\n", | 667 | ch->id, fsm_getstate_str(ch->fsm)); |
654 | __FUNCTION__, dev->name, smp_processor_id(), ch, | ||
655 | ch->id, fsm_getstate_str(ch->fsm)); | ||
656 | 668 | ||
657 | if ((fsm_getstate(ch->fsm) != CTC_STATE_TXIDLE) || grp->in_sweep) { | 669 | if ((fsm_getstate(ch->fsm) != CTC_STATE_TXIDLE) || grp->in_sweep) { |
658 | spin_lock_irqsave(&ch->collect_lock, saveflags); | 670 | spin_lock_irqsave(&ch->collect_lock, saveflags); |
@@ -660,14 +672,8 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
660 | p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type()); | 672 | p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type()); |
661 | 673 | ||
662 | if (!p_header) { | 674 | if (!p_header) { |
663 | printk(KERN_WARNING "ctcm: OUT OF MEMORY IN %s():" | ||
664 | " Data Lost \n", __FUNCTION__); | ||
665 | |||
666 | atomic_dec(&skb->users); | ||
667 | dev_kfree_skb_any(skb); | ||
668 | spin_unlock_irqrestore(&ch->collect_lock, saveflags); | 675 | spin_unlock_irqrestore(&ch->collect_lock, saveflags); |
669 | fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev); | 676 | goto nomem_exit; |
670 | goto done; | ||
671 | } | 677 | } |
672 | 678 | ||
673 | p_header->pdu_offset = skb->len; | 679 | p_header->pdu_offset = skb->len; |
@@ -682,13 +688,10 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
682 | memcpy(skb_push(skb, PDU_HEADER_LENGTH), p_header, | 688 | memcpy(skb_push(skb, PDU_HEADER_LENGTH), p_header, |
683 | PDU_HEADER_LENGTH); | 689 | PDU_HEADER_LENGTH); |
684 | 690 | ||
685 | if (do_debug_data) { | 691 | CTCM_PR_DEBUG("%s(%s): Put on collect_q - skb len: %04x \n" |
686 | ctcm_pr_debug("ctcm: %s() Putting on collect_q" | 692 | "pdu header and data for up to 32 bytes:\n", |
687 | " - skb len: %04x \n", __FUNCTION__, skb->len); | 693 | __func__, dev->name, skb->len); |
688 | ctcm_pr_debug("ctcm: %s() pdu header and data" | 694 | CTCM_D3_DUMP((char *)skb->data, min_t(int, 32, skb->len)); |
689 | " for up to 32 bytes\n", __FUNCTION__); | ||
690 | ctcmpc_dump32((char *)skb->data, skb->len); | ||
691 | } | ||
692 | 695 | ||
693 | skb_queue_tail(&ch->collect_queue, skb); | 696 | skb_queue_tail(&ch->collect_queue, skb); |
694 | ch->collect_len += skb->len; | 697 | ch->collect_len += skb->len; |
@@ -713,12 +716,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
713 | if (hi) { | 716 | if (hi) { |
714 | nskb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); | 717 | nskb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); |
715 | if (!nskb) { | 718 | if (!nskb) { |
716 | printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY" | 719 | goto nomem_exit; |
717 | "- Data Lost \n", __FUNCTION__); | ||
718 | atomic_dec(&skb->users); | ||
719 | dev_kfree_skb_any(skb); | ||
720 | fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev); | ||
721 | goto done; | ||
722 | } else { | 720 | } else { |
723 | memcpy(skb_put(nskb, skb->len), skb->data, skb->len); | 721 | memcpy(skb_put(nskb, skb->len), skb->data, skb->len); |
724 | atomic_inc(&nskb->users); | 722 | atomic_inc(&nskb->users); |
@@ -730,15 +728,8 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
730 | 728 | ||
731 | p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type()); | 729 | p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type()); |
732 | 730 | ||
733 | if (!p_header) { | 731 | if (!p_header) |
734 | printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY" | 732 | goto nomem_exit; |
735 | ": Data Lost \n", __FUNCTION__); | ||
736 | |||
737 | atomic_dec(&skb->users); | ||
738 | dev_kfree_skb_any(skb); | ||
739 | fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev); | ||
740 | goto done; | ||
741 | } | ||
742 | 733 | ||
743 | p_header->pdu_offset = skb->len; | 734 | p_header->pdu_offset = skb->len; |
744 | p_header->pdu_proto = 0x01; | 735 | p_header->pdu_proto = 0x01; |
@@ -768,15 +759,8 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
768 | ch->prof.txlen += skb->len - PDU_HEADER_LENGTH; | 759 | ch->prof.txlen += skb->len - PDU_HEADER_LENGTH; |
769 | 760 | ||
770 | header = kmalloc(TH_HEADER_LENGTH, gfp_type()); | 761 | header = kmalloc(TH_HEADER_LENGTH, gfp_type()); |
771 | 762 | if (!header) | |
772 | if (!header) { | 763 | goto nomem_exit; |
773 | printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY: Data Lost \n", | ||
774 | __FUNCTION__); | ||
775 | atomic_dec(&skb->users); | ||
776 | dev_kfree_skb_any(skb); | ||
777 | fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev); | ||
778 | goto done; | ||
779 | } | ||
780 | 764 | ||
781 | header->th_seg = 0x00; | 765 | header->th_seg = 0x00; |
782 | header->th_ch_flag = TH_HAS_PDU; /* Normal data */ | 766 | header->th_ch_flag = TH_HAS_PDU; /* Normal data */ |
@@ -785,41 +769,31 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
785 | ch->th_seq_num++; | 769 | ch->th_seq_num++; |
786 | header->th_seq_num = ch->th_seq_num; | 770 | header->th_seq_num = ch->th_seq_num; |
787 | 771 | ||
788 | if (do_debug_data) | 772 | CTCM_PR_DBGDATA("%s(%s) ToVTAM_th_seq= %08x\n" , |
789 | ctcm_pr_debug("ctcm: %s() ToVTAM_th_seq= %08x\n" , | 773 | __func__, dev->name, ch->th_seq_num); |
790 | __FUNCTION__, ch->th_seq_num); | ||
791 | 774 | ||
792 | /* put the TH on the packet */ | 775 | /* put the TH on the packet */ |
793 | memcpy(skb_push(skb, TH_HEADER_LENGTH), header, TH_HEADER_LENGTH); | 776 | memcpy(skb_push(skb, TH_HEADER_LENGTH), header, TH_HEADER_LENGTH); |
794 | 777 | ||
795 | kfree(header); | 778 | kfree(header); |
796 | 779 | ||
797 | if (do_debug_data) { | 780 | CTCM_PR_DBGDATA("%s(%s): skb len: %04x\n - pdu header and data for " |
798 | ctcm_pr_debug("ctcm: %s(): skb len: %04x \n", | 781 | "up to 32 bytes sent to vtam:\n", |
799 | __FUNCTION__, skb->len); | 782 | __func__, dev->name, skb->len); |
800 | ctcm_pr_debug("ctcm: %s(): pdu header and data for up to 32 " | 783 | CTCM_D3_DUMP((char *)skb->data, min_t(int, 32, skb->len)); |
801 | "bytes sent to vtam\n", __FUNCTION__); | ||
802 | ctcmpc_dump32((char *)skb->data, skb->len); | ||
803 | } | ||
804 | 784 | ||
805 | ch->ccw[4].count = skb->len; | 785 | ch->ccw[4].count = skb->len; |
806 | if (set_normalized_cda(&ch->ccw[4], skb->data)) { | 786 | if (set_normalized_cda(&ch->ccw[4], skb->data)) { |
807 | /* | 787 | /* |
808 | * idal allocation failed, try via copying to | 788 | * idal allocation failed, try via copying to trans_skb. |
809 | * trans_skb. trans_skb usually has a pre-allocated | 789 | * trans_skb usually has a pre-allocated idal. |
810 | * idal. | ||
811 | */ | 790 | */ |
812 | if (ctcm_checkalloc_buffer(ch)) { | 791 | if (ctcm_checkalloc_buffer(ch)) { |
813 | /* | 792 | /* |
814 | * Remove our header. It gets added | 793 | * Remove our header. |
815 | * again on retransmit. | 794 | * It gets added again on retransmit. |
816 | */ | 795 | */ |
817 | atomic_dec(&skb->users); | 796 | goto nomem_exit; |
818 | dev_kfree_skb_any(skb); | ||
819 | printk(KERN_WARNING "ctcm: %s()OUT OF MEMORY:" | ||
820 | " Data Lost \n", __FUNCTION__); | ||
821 | fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev); | ||
822 | goto done; | ||
823 | } | 797 | } |
824 | 798 | ||
825 | skb_reset_tail_pointer(ch->trans_skb); | 799 | skb_reset_tail_pointer(ch->trans_skb); |
@@ -829,14 +803,11 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
829 | atomic_dec(&skb->users); | 803 | atomic_dec(&skb->users); |
830 | dev_kfree_skb_irq(skb); | 804 | dev_kfree_skb_irq(skb); |
831 | ccw_idx = 0; | 805 | ccw_idx = 0; |
832 | if (do_debug_data) { | 806 | CTCM_PR_DBGDATA("%s(%s): trans_skb len: %04x\n" |
833 | ctcm_pr_debug("ctcm: %s() TRANS skb len: %d \n", | 807 | "up to 32 bytes sent to vtam:\n", |
834 | __FUNCTION__, ch->trans_skb->len); | 808 | __func__, dev->name, ch->trans_skb->len); |
835 | ctcm_pr_debug("ctcm: %s up to 32 bytes of data" | 809 | CTCM_D3_DUMP((char *)ch->trans_skb->data, |
836 | " sent to vtam\n", __FUNCTION__); | 810 | min_t(int, 32, ch->trans_skb->len)); |
837 | ctcmpc_dump32((char *)ch->trans_skb->data, | ||
838 | ch->trans_skb->len); | ||
839 | } | ||
840 | } else { | 811 | } else { |
841 | skb_queue_tail(&ch->io_queue, skb); | 812 | skb_queue_tail(&ch->io_queue, skb); |
842 | ccw_idx = 3; | 813 | ccw_idx = 3; |
@@ -865,13 +836,21 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
865 | priv->stats.tx_packets++; | 836 | priv->stats.tx_packets++; |
866 | priv->stats.tx_bytes += skb->len - TH_HEADER_LENGTH; | 837 | priv->stats.tx_bytes += skb->len - TH_HEADER_LENGTH; |
867 | } | 838 | } |
868 | if (ch->th_seq_num > 0xf0000000) /* Chose 4Billion at random. */ | 839 | if (ch->th_seq_num > 0xf0000000) /* Chose at random. */ |
869 | ctcmpc_send_sweep_req(ch); | 840 | ctcmpc_send_sweep_req(ch); |
870 | 841 | ||
842 | goto done; | ||
843 | nomem_exit: | ||
844 | CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_CRIT, | ||
845 | "%s(%s): MEMORY allocation ERROR\n", | ||
846 | CTCM_FUNTAIL, ch->id); | ||
847 | rc = -ENOMEM; | ||
848 | atomic_dec(&skb->users); | ||
849 | dev_kfree_skb_any(skb); | ||
850 | fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev); | ||
871 | done: | 851 | done: |
872 | if (do_debug) | 852 | CTCM_PR_DEBUG("Exit %s(%s)\n", __func__, dev->name); |
873 | ctcm_pr_debug("ctcm exit: %s %s()\n", dev->name, __FUNCTION__); | 853 | return rc; |
874 | return 0; | ||
875 | } | 854 | } |
876 | 855 | ||
877 | /** | 856 | /** |
@@ -888,20 +867,19 @@ done: | |||
888 | /* first merge version - leaving both functions separated */ | 867 | /* first merge version - leaving both functions separated */ |
889 | static int ctcm_tx(struct sk_buff *skb, struct net_device *dev) | 868 | static int ctcm_tx(struct sk_buff *skb, struct net_device *dev) |
890 | { | 869 | { |
891 | int rc = 0; | 870 | struct ctcm_priv *priv = dev->priv; |
892 | struct ctcm_priv *priv; | ||
893 | |||
894 | CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__); | ||
895 | priv = dev->priv; | ||
896 | 871 | ||
897 | if (skb == NULL) { | 872 | if (skb == NULL) { |
898 | ctcm_pr_warn("%s: NULL sk_buff passed\n", dev->name); | 873 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR, |
874 | "%s(%s): NULL sk_buff passed", | ||
875 | CTCM_FUNTAIL, dev->name); | ||
899 | priv->stats.tx_dropped++; | 876 | priv->stats.tx_dropped++; |
900 | return 0; | 877 | return 0; |
901 | } | 878 | } |
902 | if (skb_headroom(skb) < (LL_HEADER_LENGTH + 2)) { | 879 | if (skb_headroom(skb) < (LL_HEADER_LENGTH + 2)) { |
903 | ctcm_pr_warn("%s: Got sk_buff with head room < %ld bytes\n", | 880 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR, |
904 | dev->name, LL_HEADER_LENGTH + 2); | 881 | "%s(%s): Got sk_buff with head room < %ld bytes", |
882 | CTCM_FUNTAIL, dev->name, LL_HEADER_LENGTH + 2); | ||
905 | dev_kfree_skb(skb); | 883 | dev_kfree_skb(skb); |
906 | priv->stats.tx_dropped++; | 884 | priv->stats.tx_dropped++; |
907 | return 0; | 885 | return 0; |
@@ -925,51 +903,43 @@ static int ctcm_tx(struct sk_buff *skb, struct net_device *dev) | |||
925 | 903 | ||
926 | dev->trans_start = jiffies; | 904 | dev->trans_start = jiffies; |
927 | if (ctcm_transmit_skb(priv->channel[WRITE], skb) != 0) | 905 | if (ctcm_transmit_skb(priv->channel[WRITE], skb) != 0) |
928 | rc = 1; | 906 | return 1; |
929 | return rc; | 907 | return 0; |
930 | } | 908 | } |
931 | 909 | ||
932 | /* unmerged MPC variant of ctcm_tx */ | 910 | /* unmerged MPC variant of ctcm_tx */ |
933 | static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev) | 911 | static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev) |
934 | { | 912 | { |
935 | int len = 0; | 913 | int len = 0; |
936 | struct ctcm_priv *priv = NULL; | 914 | struct ctcm_priv *priv = dev->priv; |
937 | struct mpc_group *grp = NULL; | 915 | struct mpc_group *grp = priv->mpcg; |
938 | struct sk_buff *newskb = NULL; | 916 | struct sk_buff *newskb = NULL; |
939 | 917 | ||
940 | if (do_debug) | ||
941 | ctcm_pr_debug("ctcmpc enter: %s(): skb:%0lx\n", | ||
942 | __FUNCTION__, (unsigned long)skb); | ||
943 | |||
944 | CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG, | ||
945 | "ctcmpc enter: %s(): skb:%0lx\n", | ||
946 | __FUNCTION__, (unsigned long)skb); | ||
947 | |||
948 | priv = dev->priv; | ||
949 | grp = priv->mpcg; | ||
950 | /* | 918 | /* |
951 | * Some sanity checks ... | 919 | * Some sanity checks ... |
952 | */ | 920 | */ |
953 | if (skb == NULL) { | 921 | if (skb == NULL) { |
954 | ctcm_pr_warn("ctcmpc: %s: NULL sk_buff passed\n", dev->name); | 922 | CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR, |
923 | "%s(%s): NULL sk_buff passed", | ||
924 | CTCM_FUNTAIL, dev->name); | ||
955 | priv->stats.tx_dropped++; | 925 | priv->stats.tx_dropped++; |
956 | goto done; | 926 | goto done; |
957 | } | 927 | } |
958 | if (skb_headroom(skb) < (TH_HEADER_LENGTH + PDU_HEADER_LENGTH)) { | 928 | if (skb_headroom(skb) < (TH_HEADER_LENGTH + PDU_HEADER_LENGTH)) { |
959 | CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_WARN, | 929 | CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ERROR, |
960 | "%s: Got sk_buff with head room < %ld bytes\n", | 930 | "%s(%s): Got sk_buff with head room < %ld bytes", |
961 | dev->name, TH_HEADER_LENGTH + PDU_HEADER_LENGTH); | 931 | CTCM_FUNTAIL, dev->name, |
932 | TH_HEADER_LENGTH + PDU_HEADER_LENGTH); | ||
962 | 933 | ||
963 | if (do_debug_data) | 934 | CTCM_D3_DUMP((char *)skb->data, min_t(int, 32, skb->len)); |
964 | ctcmpc_dump32((char *)skb->data, skb->len); | ||
965 | 935 | ||
966 | len = skb->len + TH_HEADER_LENGTH + PDU_HEADER_LENGTH; | 936 | len = skb->len + TH_HEADER_LENGTH + PDU_HEADER_LENGTH; |
967 | newskb = __dev_alloc_skb(len, gfp_type() | GFP_DMA); | 937 | newskb = __dev_alloc_skb(len, gfp_type() | GFP_DMA); |
968 | 938 | ||
969 | if (!newskb) { | 939 | if (!newskb) { |
970 | printk(KERN_WARNING "ctcmpc: %s() OUT OF MEMORY-" | 940 | CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ERROR, |
971 | "Data Lost\n", | 941 | "%s: %s: __dev_alloc_skb failed", |
972 | __FUNCTION__); | 942 | __func__, dev->name); |
973 | 943 | ||
974 | dev_kfree_skb_any(skb); | 944 | dev_kfree_skb_any(skb); |
975 | priv->stats.tx_dropped++; | 945 | priv->stats.tx_dropped++; |
@@ -993,9 +963,9 @@ static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev) | |||
993 | if ((fsm_getstate(priv->fsm) != DEV_STATE_RUNNING) || | 963 | if ((fsm_getstate(priv->fsm) != DEV_STATE_RUNNING) || |
994 | (fsm_getstate(grp->fsm) < MPCG_STATE_XID2INITW)) { | 964 | (fsm_getstate(grp->fsm) < MPCG_STATE_XID2INITW)) { |
995 | dev_kfree_skb_any(skb); | 965 | dev_kfree_skb_any(skb); |
996 | printk(KERN_INFO "ctcmpc: %s() DATA RCVD - MPC GROUP " | 966 | CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR, |
997 | "NOT ACTIVE - DROPPED\n", | 967 | "%s(%s): inactive MPCGROUP - dropped", |
998 | __FUNCTION__); | 968 | CTCM_FUNTAIL, dev->name); |
999 | priv->stats.tx_dropped++; | 969 | priv->stats.tx_dropped++; |
1000 | priv->stats.tx_errors++; | 970 | priv->stats.tx_errors++; |
1001 | priv->stats.tx_carrier_errors++; | 971 | priv->stats.tx_carrier_errors++; |
@@ -1003,8 +973,9 @@ static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev) | |||
1003 | } | 973 | } |
1004 | 974 | ||
1005 | if (ctcm_test_and_set_busy(dev)) { | 975 | if (ctcm_test_and_set_busy(dev)) { |
1006 | printk(KERN_WARNING "%s:DEVICE ERR - UNRECOVERABLE DATA LOSS\n", | 976 | CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR, |
1007 | __FUNCTION__); | 977 | "%s(%s): device busy - dropped", |
978 | CTCM_FUNTAIL, dev->name); | ||
1008 | dev_kfree_skb_any(skb); | 979 | dev_kfree_skb_any(skb); |
1009 | priv->stats.tx_dropped++; | 980 | priv->stats.tx_dropped++; |
1010 | priv->stats.tx_errors++; | 981 | priv->stats.tx_errors++; |
@@ -1015,12 +986,9 @@ static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev) | |||
1015 | 986 | ||
1016 | dev->trans_start = jiffies; | 987 | dev->trans_start = jiffies; |
1017 | if (ctcmpc_transmit_skb(priv->channel[WRITE], skb) != 0) { | 988 | if (ctcmpc_transmit_skb(priv->channel[WRITE], skb) != 0) { |
1018 | printk(KERN_WARNING "ctcmpc: %s() DEVICE ERROR" | 989 | CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR, |
1019 | ": Data Lost \n", | 990 | "%s(%s): device error - dropped", |
1020 | __FUNCTION__); | 991 | CTCM_FUNTAIL, dev->name); |
1021 | printk(KERN_WARNING "ctcmpc: %s() DEVICE ERROR" | ||
1022 | " - UNRECOVERABLE DATA LOSS\n", | ||
1023 | __FUNCTION__); | ||
1024 | dev_kfree_skb_any(skb); | 992 | dev_kfree_skb_any(skb); |
1025 | priv->stats.tx_dropped++; | 993 | priv->stats.tx_dropped++; |
1026 | priv->stats.tx_errors++; | 994 | priv->stats.tx_errors++; |
@@ -1054,8 +1022,6 @@ static int ctcm_change_mtu(struct net_device *dev, int new_mtu) | |||
1054 | struct ctcm_priv *priv; | 1022 | struct ctcm_priv *priv; |
1055 | int max_bufsize; | 1023 | int max_bufsize; |
1056 | 1024 | ||
1057 | CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__); | ||
1058 | |||
1059 | if (new_mtu < 576 || new_mtu > 65527) | 1025 | if (new_mtu < 576 || new_mtu > 65527) |
1060 | return -EINVAL; | 1026 | return -EINVAL; |
1061 | 1027 | ||
@@ -1087,30 +1053,13 @@ static struct net_device_stats *ctcm_stats(struct net_device *dev) | |||
1087 | return &((struct ctcm_priv *)dev->priv)->stats; | 1053 | return &((struct ctcm_priv *)dev->priv)->stats; |
1088 | } | 1054 | } |
1089 | 1055 | ||
1090 | |||
1091 | static void ctcm_netdev_unregister(struct net_device *dev) | ||
1092 | { | ||
1093 | CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__); | ||
1094 | if (!dev) | ||
1095 | return; | ||
1096 | unregister_netdev(dev); | ||
1097 | } | ||
1098 | |||
1099 | static int ctcm_netdev_register(struct net_device *dev) | ||
1100 | { | ||
1101 | CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__); | ||
1102 | return register_netdev(dev); | ||
1103 | } | ||
1104 | |||
1105 | static void ctcm_free_netdevice(struct net_device *dev) | 1056 | static void ctcm_free_netdevice(struct net_device *dev) |
1106 | { | 1057 | { |
1107 | struct ctcm_priv *priv; | 1058 | struct ctcm_priv *priv; |
1108 | struct mpc_group *grp; | 1059 | struct mpc_group *grp; |
1109 | 1060 | ||
1110 | CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__); | 1061 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, |
1111 | 1062 | "%s(%s)", CTCM_FUNTAIL, dev->name); | |
1112 | if (!dev) | ||
1113 | return; | ||
1114 | priv = dev->priv; | 1063 | priv = dev->priv; |
1115 | if (priv) { | 1064 | if (priv) { |
1116 | grp = priv->mpcg; | 1065 | grp = priv->mpcg; |
@@ -1171,7 +1120,9 @@ static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv) | |||
1171 | dev = alloc_netdev(0, CTC_DEVICE_GENE, ctcm_dev_setup); | 1120 | dev = alloc_netdev(0, CTC_DEVICE_GENE, ctcm_dev_setup); |
1172 | 1121 | ||
1173 | if (!dev) { | 1122 | if (!dev) { |
1174 | ctcm_pr_err("%s: Out of memory\n", __FUNCTION__); | 1123 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_CRIT, |
1124 | "%s: MEMORY allocation ERROR", | ||
1125 | CTCM_FUNTAIL); | ||
1175 | return NULL; | 1126 | return NULL; |
1176 | } | 1127 | } |
1177 | dev->priv = priv; | 1128 | dev->priv = priv; |
@@ -1209,6 +1160,7 @@ static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv) | |||
1209 | } | 1160 | } |
1210 | 1161 | ||
1211 | CTCMY_DBF_DEV(SETUP, dev, "finished"); | 1162 | CTCMY_DBF_DEV(SETUP, dev, "finished"); |
1163 | |||
1212 | return dev; | 1164 | return dev; |
1213 | } | 1165 | } |
1214 | 1166 | ||
@@ -1226,18 +1178,24 @@ static void ctcm_irq_handler(struct ccw_device *cdev, | |||
1226 | struct net_device *dev; | 1178 | struct net_device *dev; |
1227 | struct ctcm_priv *priv; | 1179 | struct ctcm_priv *priv; |
1228 | struct ccwgroup_device *cgdev; | 1180 | struct ccwgroup_device *cgdev; |
1181 | int cstat; | ||
1182 | int dstat; | ||
1183 | |||
1184 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, | ||
1185 | "Enter %s(%s)", CTCM_FUNTAIL, &cdev->dev.bus_id); | ||
1229 | 1186 | ||
1230 | CTCM_DBF_TEXT(TRACE, CTC_DBF_DEBUG, __FUNCTION__); | ||
1231 | if (ctcm_check_irb_error(cdev, irb)) | 1187 | if (ctcm_check_irb_error(cdev, irb)) |
1232 | return; | 1188 | return; |
1233 | 1189 | ||
1234 | cgdev = dev_get_drvdata(&cdev->dev); | 1190 | cgdev = dev_get_drvdata(&cdev->dev); |
1235 | 1191 | ||
1192 | cstat = irb->scsw.cmd.cstat; | ||
1193 | dstat = irb->scsw.cmd.dstat; | ||
1194 | |||
1236 | /* Check for unsolicited interrupts. */ | 1195 | /* Check for unsolicited interrupts. */ |
1237 | if (cgdev == NULL) { | 1196 | if (cgdev == NULL) { |
1238 | ctcm_pr_warn("ctcm: Got unsolicited irq: %s c-%02x d-%02x\n", | 1197 | ctcm_pr_warn("ctcm: Got unsolicited irq: c-%02x d-%02x\n", |
1239 | cdev->dev.bus_id, irb->scsw.cmd.cstat, | 1198 | cstat, dstat); |
1240 | irb->scsw.cmd.dstat); | ||
1241 | return; | 1199 | return; |
1242 | } | 1200 | } |
1243 | 1201 | ||
@@ -1254,26 +1212,22 @@ static void ctcm_irq_handler(struct ccw_device *cdev, | |||
1254 | return; | 1212 | return; |
1255 | } | 1213 | } |
1256 | 1214 | ||
1257 | dev = (struct net_device *)(ch->netdev); | 1215 | dev = ch->netdev; |
1258 | if (dev == NULL) { | 1216 | if (dev == NULL) { |
1259 | ctcm_pr_crit("ctcm: %s dev=NULL bus_id=%s, ch=0x%p\n", | 1217 | ctcm_pr_crit("ctcm: %s dev=NULL bus_id=%s, ch=0x%p\n", |
1260 | __FUNCTION__, cdev->dev.bus_id, ch); | 1218 | __func__, cdev->dev.bus_id, ch); |
1261 | return; | 1219 | return; |
1262 | } | 1220 | } |
1263 | 1221 | ||
1264 | if (do_debug) | 1222 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, |
1265 | ctcm_pr_debug("%s: interrupt for device: %s " | 1223 | "%s(%s): int. for %s: cstat=%02x dstat=%02x", |
1266 | "received c-%02x d-%02x\n", | 1224 | CTCM_FUNTAIL, dev->name, ch->id, cstat, dstat); |
1267 | dev->name, | ||
1268 | ch->id, | ||
1269 | irb->scsw.cmd.cstat, | ||
1270 | irb->scsw.cmd.dstat); | ||
1271 | 1225 | ||
1272 | /* Copy interruption response block. */ | 1226 | /* Copy interruption response block. */ |
1273 | memcpy(ch->irb, irb, sizeof(struct irb)); | 1227 | memcpy(ch->irb, irb, sizeof(struct irb)); |
1274 | 1228 | ||
1275 | /* Check for good subchannel return code, otherwise error message */ | ||
1276 | if (irb->scsw.cmd.cstat) { | 1229 | if (irb->scsw.cmd.cstat) { |
1230 | /* Check for good subchannel return code, otherwise error message */ | ||
1277 | fsm_event(ch->fsm, CTC_EVENT_SC_UNKNOWN, ch); | 1231 | fsm_event(ch->fsm, CTC_EVENT_SC_UNKNOWN, ch); |
1278 | ctcm_pr_warn("%s: subchannel check for dev: %s - %02x %02x\n", | 1232 | ctcm_pr_warn("%s: subchannel check for dev: %s - %02x %02x\n", |
1279 | dev->name, ch->id, irb->scsw.cmd.cstat, | 1233 | dev->name, ch->id, irb->scsw.cmd.cstat, |
@@ -1283,6 +1237,11 @@ static void ctcm_irq_handler(struct ccw_device *cdev, | |||
1283 | 1237 | ||
1284 | /* Check the reason-code of a unit check */ | 1238 | /* Check the reason-code of a unit check */ |
1285 | if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) { | 1239 | if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) { |
1240 | if ((irb->ecw[0] & ch->sense_rc) == 0) | ||
1241 | /* print it only once */ | ||
1242 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_INFO, | ||
1243 | "%s(%s): sense=%02x, ds=%02x", | ||
1244 | CTCM_FUNTAIL, ch->id, irb->ecw[0], dstat); | ||
1286 | ccw_unit_check(ch, irb->ecw[0]); | 1245 | ccw_unit_check(ch, irb->ecw[0]); |
1287 | return; | 1246 | return; |
1288 | } | 1247 | } |
@@ -1320,14 +1279,18 @@ static int ctcm_probe_device(struct ccwgroup_device *cgdev) | |||
1320 | struct ctcm_priv *priv; | 1279 | struct ctcm_priv *priv; |
1321 | int rc; | 1280 | int rc; |
1322 | 1281 | ||
1323 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s %p", __FUNCTION__, cgdev); | 1282 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, |
1283 | "%s %p", | ||
1284 | __func__, cgdev); | ||
1324 | 1285 | ||
1325 | if (!get_device(&cgdev->dev)) | 1286 | if (!get_device(&cgdev->dev)) |
1326 | return -ENODEV; | 1287 | return -ENODEV; |
1327 | 1288 | ||
1328 | priv = kzalloc(sizeof(struct ctcm_priv), GFP_KERNEL); | 1289 | priv = kzalloc(sizeof(struct ctcm_priv), GFP_KERNEL); |
1329 | if (!priv) { | 1290 | if (!priv) { |
1330 | ctcm_pr_err("%s: Out of memory\n", __FUNCTION__); | 1291 | CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR, |
1292 | "%s: memory allocation failure", | ||
1293 | CTCM_FUNTAIL); | ||
1331 | put_device(&cgdev->dev); | 1294 | put_device(&cgdev->dev); |
1332 | return -ENOMEM; | 1295 | return -ENOMEM; |
1333 | } | 1296 | } |
@@ -1364,10 +1327,13 @@ static int add_channel(struct ccw_device *cdev, enum channel_types type, | |||
1364 | int ccw_num; | 1327 | int ccw_num; |
1365 | int rc = 0; | 1328 | int rc = 0; |
1366 | 1329 | ||
1367 | CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__); | 1330 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, |
1331 | "%s(%s), type %d, proto %d", | ||
1332 | __func__, cdev->dev.bus_id, type, priv->protocol); | ||
1333 | |||
1368 | ch = kzalloc(sizeof(struct channel), GFP_KERNEL); | 1334 | ch = kzalloc(sizeof(struct channel), GFP_KERNEL); |
1369 | if (ch == NULL) | 1335 | if (ch == NULL) |
1370 | goto nomem_return; | 1336 | return -ENOMEM; |
1371 | 1337 | ||
1372 | ch->protocol = priv->protocol; | 1338 | ch->protocol = priv->protocol; |
1373 | if (IS_MPC(priv)) { | 1339 | if (IS_MPC(priv)) { |
@@ -1478,7 +1444,7 @@ static int add_channel(struct ccw_device *cdev, enum channel_types type, | |||
1478 | if (*c && (!strncmp((*c)->id, ch->id, CTCM_ID_SIZE))) { | 1444 | if (*c && (!strncmp((*c)->id, ch->id, CTCM_ID_SIZE))) { |
1479 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, | 1445 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, |
1480 | "%s (%s) already in list, using old entry", | 1446 | "%s (%s) already in list, using old entry", |
1481 | __FUNCTION__, (*c)->id); | 1447 | __func__, (*c)->id); |
1482 | 1448 | ||
1483 | goto free_return; | 1449 | goto free_return; |
1484 | } | 1450 | } |
@@ -1498,11 +1464,10 @@ static int add_channel(struct ccw_device *cdev, enum channel_types type, | |||
1498 | return 0; | 1464 | return 0; |
1499 | 1465 | ||
1500 | nomem_return: | 1466 | nomem_return: |
1501 | ctcm_pr_warn("ctcm: Out of memory in %s\n", __FUNCTION__); | ||
1502 | rc = -ENOMEM; | 1467 | rc = -ENOMEM; |
1503 | 1468 | ||
1504 | free_return: /* note that all channel pointers are 0 or valid */ | 1469 | free_return: /* note that all channel pointers are 0 or valid */ |
1505 | kfree(ch->ccw); /* TODO: check that again */ | 1470 | kfree(ch->ccw); |
1506 | kfree(ch->discontact_th); | 1471 | kfree(ch->discontact_th); |
1507 | kfree_fsm(ch->fsm); | 1472 | kfree_fsm(ch->fsm); |
1508 | kfree(ch->irb); | 1473 | kfree(ch->irb); |
@@ -1540,48 +1505,48 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev) | |||
1540 | enum channel_types type; | 1505 | enum channel_types type; |
1541 | struct ctcm_priv *priv; | 1506 | struct ctcm_priv *priv; |
1542 | struct net_device *dev; | 1507 | struct net_device *dev; |
1508 | struct ccw_device *cdev0; | ||
1509 | struct ccw_device *cdev1; | ||
1543 | int ret; | 1510 | int ret; |
1544 | 1511 | ||
1545 | CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__); | ||
1546 | |||
1547 | priv = dev_get_drvdata(&cgdev->dev); | 1512 | priv = dev_get_drvdata(&cgdev->dev); |
1548 | if (!priv) | 1513 | if (!priv) |
1549 | return -ENODEV; | 1514 | return -ENODEV; |
1550 | 1515 | ||
1551 | type = get_channel_type(&cgdev->cdev[0]->id); | 1516 | cdev0 = cgdev->cdev[0]; |
1517 | cdev1 = cgdev->cdev[1]; | ||
1518 | |||
1519 | type = get_channel_type(&cdev0->id); | ||
1552 | 1520 | ||
1553 | snprintf(read_id, CTCM_ID_SIZE, "ch-%s", cgdev->cdev[0]->dev.bus_id); | 1521 | snprintf(read_id, CTCM_ID_SIZE, "ch-%s", cdev0->dev.bus_id); |
1554 | snprintf(write_id, CTCM_ID_SIZE, "ch-%s", cgdev->cdev[1]->dev.bus_id); | 1522 | snprintf(write_id, CTCM_ID_SIZE, "ch-%s", cdev1->dev.bus_id); |
1555 | 1523 | ||
1556 | ret = add_channel(cgdev->cdev[0], type, priv); | 1524 | ret = add_channel(cdev0, type, priv); |
1557 | if (ret) | 1525 | if (ret) |
1558 | return ret; | 1526 | return ret; |
1559 | ret = add_channel(cgdev->cdev[1], type, priv); | 1527 | ret = add_channel(cdev1, type, priv); |
1560 | if (ret) | 1528 | if (ret) |
1561 | return ret; | 1529 | return ret; |
1562 | 1530 | ||
1563 | ret = ccw_device_set_online(cgdev->cdev[0]); | 1531 | ret = ccw_device_set_online(cdev0); |
1564 | if (ret != 0) { | 1532 | if (ret != 0) { |
1565 | CTCM_DBF_TEXT(SETUP, CTC_DBF_WARN, | 1533 | /* may be ok to fail now - can be done later */ |
1566 | "ccw_device_set_online (cdev[0]) failed "); | 1534 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE, |
1567 | ctcm_pr_warn("ccw_device_set_online (cdev[0]) failed " | 1535 | "%s(%s) set_online rc=%d", |
1568 | "with ret = %d\n", ret); | 1536 | CTCM_FUNTAIL, read_id, ret); |
1569 | } | 1537 | } |
1570 | 1538 | ||
1571 | ret = ccw_device_set_online(cgdev->cdev[1]); | 1539 | ret = ccw_device_set_online(cdev1); |
1572 | if (ret != 0) { | 1540 | if (ret != 0) { |
1573 | CTCM_DBF_TEXT(SETUP, CTC_DBF_WARN, | 1541 | /* may be ok to fail now - can be done later */ |
1574 | "ccw_device_set_online (cdev[1]) failed "); | 1542 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE, |
1575 | ctcm_pr_warn("ccw_device_set_online (cdev[1]) failed " | 1543 | "%s(%s) set_online rc=%d", |
1576 | "with ret = %d\n", ret); | 1544 | CTCM_FUNTAIL, write_id, ret); |
1577 | } | 1545 | } |
1578 | 1546 | ||
1579 | dev = ctcm_init_netdevice(priv); | 1547 | dev = ctcm_init_netdevice(priv); |
1580 | 1548 | if (dev == NULL) | |
1581 | if (dev == NULL) { | 1549 | goto out; |
1582 | ctcm_pr_warn("ctcm_init_netdevice failed\n"); | ||
1583 | goto out; | ||
1584 | } | ||
1585 | 1550 | ||
1586 | for (direction = READ; direction <= WRITE; direction++) { | 1551 | for (direction = READ; direction <= WRITE; direction++) { |
1587 | priv->channel[direction] = | 1552 | priv->channel[direction] = |
@@ -1590,8 +1555,7 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev) | |||
1590 | if (priv->channel[direction] == NULL) { | 1555 | if (priv->channel[direction] == NULL) { |
1591 | if (direction == WRITE) | 1556 | if (direction == WRITE) |
1592 | channel_free(priv->channel[READ]); | 1557 | channel_free(priv->channel[READ]); |
1593 | ctcm_free_netdevice(dev); | 1558 | goto out_dev; |
1594 | goto out; | ||
1595 | } | 1559 | } |
1596 | priv->channel[direction]->netdev = dev; | 1560 | priv->channel[direction]->netdev = dev; |
1597 | priv->channel[direction]->protocol = priv->protocol; | 1561 | priv->channel[direction]->protocol = priv->protocol; |
@@ -1600,26 +1564,24 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev) | |||
1600 | /* sysfs magic */ | 1564 | /* sysfs magic */ |
1601 | SET_NETDEV_DEV(dev, &cgdev->dev); | 1565 | SET_NETDEV_DEV(dev, &cgdev->dev); |
1602 | 1566 | ||
1603 | if (ctcm_netdev_register(dev) != 0) { | 1567 | if (register_netdev(dev)) |
1604 | ctcm_free_netdevice(dev); | 1568 | goto out_dev; |
1605 | goto out; | ||
1606 | } | ||
1607 | 1569 | ||
1608 | if (ctcm_add_attributes(&cgdev->dev)) { | 1570 | if (ctcm_add_attributes(&cgdev->dev)) { |
1609 | ctcm_netdev_unregister(dev); | 1571 | unregister_netdev(dev); |
1610 | /* dev->priv = NULL; why that ???? */ | 1572 | goto out_dev; |
1611 | ctcm_free_netdevice(dev); | ||
1612 | goto out; | ||
1613 | } | 1573 | } |
1614 | 1574 | ||
1615 | strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name)); | 1575 | strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name)); |
1616 | 1576 | ||
1617 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, | 1577 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, |
1618 | "setup(%s) ok : r/w = %s / %s, proto : %d", | 1578 | "setup(%s) OK : r/w = %s/%s, protocol : %d", dev->name, |
1619 | dev->name, priv->channel[READ]->id, | 1579 | priv->channel[READ]->id, |
1620 | priv->channel[WRITE]->id, priv->protocol); | 1580 | priv->channel[WRITE]->id, priv->protocol); |
1621 | 1581 | ||
1622 | return 0; | 1582 | return 0; |
1583 | out_dev: | ||
1584 | ctcm_free_netdevice(dev); | ||
1623 | out: | 1585 | out: |
1624 | ccw_device_set_offline(cgdev->cdev[1]); | 1586 | ccw_device_set_offline(cgdev->cdev[1]); |
1625 | ccw_device_set_offline(cgdev->cdev[0]); | 1587 | ccw_device_set_offline(cgdev->cdev[0]); |
@@ -1658,8 +1620,7 @@ static int ctcm_shutdown_device(struct ccwgroup_device *cgdev) | |||
1658 | channel_free(priv->channel[WRITE]); | 1620 | channel_free(priv->channel[WRITE]); |
1659 | 1621 | ||
1660 | if (dev) { | 1622 | if (dev) { |
1661 | ctcm_netdev_unregister(dev); | 1623 | unregister_netdev(dev); |
1662 | /* dev->priv = NULL; why that ??? */ | ||
1663 | ctcm_free_netdevice(dev); | 1624 | ctcm_free_netdevice(dev); |
1664 | } | 1625 | } |
1665 | 1626 | ||
@@ -1682,13 +1643,16 @@ static int ctcm_shutdown_device(struct ccwgroup_device *cgdev) | |||
1682 | 1643 | ||
1683 | static void ctcm_remove_device(struct ccwgroup_device *cgdev) | 1644 | static void ctcm_remove_device(struct ccwgroup_device *cgdev) |
1684 | { | 1645 | { |
1685 | struct ctcm_priv *priv; | 1646 | struct ctcm_priv *priv = dev_get_drvdata(&cgdev->dev); |
1686 | 1647 | ||
1687 | CTCM_DBF_TEXT(SETUP, CTC_DBF_ERROR, __FUNCTION__); | 1648 | BUG_ON(priv == NULL); |
1649 | |||
1650 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, | ||
1651 | "removing device %s, r/w = %s/%s, proto : %d", | ||
1652 | priv->channel[READ]->netdev->name, | ||
1653 | priv->channel[READ]->id, priv->channel[WRITE]->id, | ||
1654 | priv->protocol); | ||
1688 | 1655 | ||
1689 | priv = dev_get_drvdata(&cgdev->dev); | ||
1690 | if (!priv) | ||
1691 | return; | ||
1692 | if (cgdev->state == CCWGROUP_ONLINE) | 1656 | if (cgdev->state == CCWGROUP_ONLINE) |
1693 | ctcm_shutdown_device(cgdev); | 1657 | ctcm_shutdown_device(cgdev); |
1694 | ctcm_remove_files(&cgdev->dev); | 1658 | ctcm_remove_files(&cgdev->dev); |
@@ -1748,8 +1712,6 @@ static int __init ctcm_init(void) | |||
1748 | 1712 | ||
1749 | ret = ctcm_register_dbf_views(); | 1713 | ret = ctcm_register_dbf_views(); |
1750 | if (ret) { | 1714 | if (ret) { |
1751 | ctcm_pr_crit("ctcm_init failed with ctcm_register_dbf_views " | ||
1752 | "rc = %d\n", ret); | ||
1753 | return ret; | 1715 | return ret; |
1754 | } | 1716 | } |
1755 | ret = register_cu3088_discipline(&ctcm_group_driver); | 1717 | ret = register_cu3088_discipline(&ctcm_group_driver); |