2286 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright IBM Corp. 2001, 20074 * Authors: Fritz Elfert (felfert@millenux.com)5 * Peter Tiedemann (ptiedem@de.ibm.com)6 * MPC additions :7 * Belinda Thompson (belindat@us.ibm.com)8 * Andy Richter (richtera@us.ibm.com)9 */10 11#undef DEBUG12#undef DEBUGDATA13#undef DEBUGCCW14 15#define KMSG_COMPONENT "ctcm"16#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt17 18#include <linux/module.h>19#include <linux/init.h>20#include <linux/kernel.h>21#include <linux/slab.h>22#include <linux/errno.h>23#include <linux/types.h>24#include <linux/interrupt.h>25#include <linux/timer.h>26#include <linux/bitops.h>27 28#include <linux/signal.h>29#include <linux/string.h>30 31#include <linux/ip.h>32#include <linux/if_arp.h>33#include <linux/tcp.h>34#include <linux/skbuff.h>35#include <linux/ctype.h>36#include <net/dst.h>37 38#include <linux/io.h>39#include <asm/ccwdev.h>40#include <asm/ccwgroup.h>41#include <linux/uaccess.h>42 43#include <asm/idals.h>44 45#include "fsm.h"46 47#include "ctcm_dbug.h"48#include "ctcm_main.h"49#include "ctcm_fsms.h"50 51const char *dev_state_names[] = {52 [DEV_STATE_STOPPED] = "Stopped",53 [DEV_STATE_STARTWAIT_RXTX] = "StartWait RXTX",54 [DEV_STATE_STARTWAIT_RX] = "StartWait RX",55 [DEV_STATE_STARTWAIT_TX] = "StartWait TX",56 [DEV_STATE_STOPWAIT_RXTX] = "StopWait RXTX",57 [DEV_STATE_STOPWAIT_RX] = "StopWait RX",58 [DEV_STATE_STOPWAIT_TX] = "StopWait TX",59 [DEV_STATE_RUNNING] = "Running",60};61 62const char *dev_event_names[] = {63 [DEV_EVENT_START] = "Start",64 [DEV_EVENT_STOP] = "Stop",65 [DEV_EVENT_RXUP] = "RX up",66 [DEV_EVENT_TXUP] = "TX up",67 [DEV_EVENT_RXDOWN] = "RX down",68 [DEV_EVENT_TXDOWN] = "TX down",69 [DEV_EVENT_RESTART] = "Restart",70};71 72const char *ctc_ch_event_names[] = {73 [CTC_EVENT_IO_SUCCESS] = "ccw_device success",74 [CTC_EVENT_IO_EBUSY] = "ccw_device busy",75 [CTC_EVENT_IO_ENODEV] = "ccw_device enodev",76 [CTC_EVENT_IO_UNKNOWN] = "ccw_device unknown",77 [CTC_EVENT_ATTNBUSY] = "Status ATTN & BUSY",78 [CTC_EVENT_ATTN] = "Status ATTN",79 [CTC_EVENT_BUSY] = "Status BUSY",80 [CTC_EVENT_UC_RCRESET] = "Unit check remote reset",81 [CTC_EVENT_UC_RSRESET] = "Unit check remote system reset",82 [CTC_EVENT_UC_TXTIMEOUT] = "Unit check TX timeout",83 [CTC_EVENT_UC_TXPARITY] = "Unit check TX parity",84 [CTC_EVENT_UC_HWFAIL] = "Unit check Hardware failure",85 [CTC_EVENT_UC_RXPARITY] = "Unit check RX parity",86 [CTC_EVENT_UC_ZERO] = "Unit check ZERO",87 [CTC_EVENT_UC_UNKNOWN] = "Unit check Unknown",88 [CTC_EVENT_SC_UNKNOWN] = "SubChannel check Unknown",89 [CTC_EVENT_MC_FAIL] = "Machine check failure",90 [CTC_EVENT_MC_GOOD] = "Machine check operational",91 [CTC_EVENT_IRQ] = "IRQ normal",92 [CTC_EVENT_FINSTAT] = "IRQ final",93 [CTC_EVENT_TIMER] = "Timer",94 [CTC_EVENT_START] = "Start",95 [CTC_EVENT_STOP] = "Stop",96 /*97 * additional MPC events98 */99 [CTC_EVENT_SEND_XID] = "XID Exchange",100 [CTC_EVENT_RSWEEP_TIMER] = "MPC Group Sweep Timer",101};102 103const char *ctc_ch_state_names[] = {104 [CTC_STATE_IDLE] = "Idle",105 [CTC_STATE_STOPPED] = "Stopped",106 [CTC_STATE_STARTWAIT] = "StartWait",107 [CTC_STATE_STARTRETRY] = "StartRetry",108 [CTC_STATE_SETUPWAIT] = "SetupWait",109 [CTC_STATE_RXINIT] = "RX init",110 [CTC_STATE_TXINIT] = "TX init",111 [CTC_STATE_RX] = "RX",112 [CTC_STATE_TX] = "TX",113 [CTC_STATE_RXIDLE] = "RX idle",114 [CTC_STATE_TXIDLE] = "TX idle",115 [CTC_STATE_RXERR] = "RX error",116 [CTC_STATE_TXERR] = "TX error",117 [CTC_STATE_TERM] = "Terminating",118 [CTC_STATE_DTERM] = "Restarting",119 [CTC_STATE_NOTOP] = "Not operational",120 /*121 * additional MPC states122 */123 [CH_XID0_PENDING] = "Pending XID0 Start",124 [CH_XID0_INPROGRESS] = "In XID0 Negotiations ",125 [CH_XID7_PENDING] = "Pending XID7 P1 Start",126 [CH_XID7_PENDING1] = "Active XID7 P1 Exchange ",127 [CH_XID7_PENDING2] = "Pending XID7 P2 Start ",128 [CH_XID7_PENDING3] = "Active XID7 P2 Exchange ",129 [CH_XID7_PENDING4] = "XID7 Complete - Pending READY ",130};131 132static void ctcm_action_nop(fsm_instance *fi, int event, void *arg);133 134/*135 * ----- static ctcm actions for channel statemachine -----136 *137*/138static void chx_txdone(fsm_instance *fi, int event, void *arg);139static void chx_rx(fsm_instance *fi, int event, void *arg);140static void chx_rxidle(fsm_instance *fi, int event, void *arg);141static void chx_firstio(fsm_instance *fi, int event, void *arg);142static void ctcm_chx_setmode(fsm_instance *fi, int event, void *arg);143static void ctcm_chx_start(fsm_instance *fi, int event, void *arg);144static void ctcm_chx_haltio(fsm_instance *fi, int event, void *arg);145static void ctcm_chx_stopped(fsm_instance *fi, int event, void *arg);146static void ctcm_chx_stop(fsm_instance *fi, int event, void *arg);147static void ctcm_chx_fail(fsm_instance *fi, int event, void *arg);148static void ctcm_chx_setuperr(fsm_instance *fi, int event, void *arg);149static void ctcm_chx_restart(fsm_instance *fi, int event, void *arg);150static void ctcm_chx_rxiniterr(fsm_instance *fi, int event, void *arg);151static void ctcm_chx_rxinitfail(fsm_instance *fi, int event, void *arg);152static void ctcm_chx_rxdisc(fsm_instance *fi, int event, void *arg);153static void ctcm_chx_txiniterr(fsm_instance *fi, int event, void *arg);154static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg);155static void ctcm_chx_iofatal(fsm_instance *fi, int event, void *arg);156 157/*158 * ----- static ctcmpc actions for ctcmpc channel statemachine -----159 *160*/161static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg);162static void ctcmpc_chx_rx(fsm_instance *fi, int event, void *arg);163static void ctcmpc_chx_firstio(fsm_instance *fi, int event, void *arg);164/* shared :165static void ctcm_chx_setmode(fsm_instance *fi, int event, void *arg);166static void ctcm_chx_start(fsm_instance *fi, int event, void *arg);167static void ctcm_chx_haltio(fsm_instance *fi, int event, void *arg);168static void ctcm_chx_stopped(fsm_instance *fi, int event, void *arg);169static void ctcm_chx_stop(fsm_instance *fi, int event, void *arg);170static void ctcm_chx_fail(fsm_instance *fi, int event, void *arg);171static void ctcm_chx_setuperr(fsm_instance *fi, int event, void *arg);172static void ctcm_chx_restart(fsm_instance *fi, int event, void *arg);173static void ctcm_chx_rxiniterr(fsm_instance *fi, int event, void *arg);174static void ctcm_chx_rxinitfail(fsm_instance *fi, int event, void *arg);175static void ctcm_chx_rxdisc(fsm_instance *fi, int event, void *arg);176static void ctcm_chx_txiniterr(fsm_instance *fi, int event, void *arg);177static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg);178static void ctcm_chx_iofatal(fsm_instance *fi, int event, void *arg);179*/180static void ctcmpc_chx_attn(fsm_instance *fsm, int event, void *arg);181static void ctcmpc_chx_attnbusy(fsm_instance *, int, void *);182static void ctcmpc_chx_resend(fsm_instance *, int, void *);183static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg);184 185/*186 * Check return code of a preceding ccw_device call, halt_IO etc...187 *188 * ch : The channel, the error belongs to.189 * Returns the error code (!= 0) to inspect.190 */191void ctcm_ccw_check_rc(struct channel *ch, int rc, char *msg)192{193 CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,194 "%s(%s): %s: %04x\n",195 CTCM_FUNTAIL, ch->id, msg, rc);196 switch (rc) {197 case -EBUSY:198 pr_info("%s: The communication peer is busy\n",199 ch->id);200 fsm_event(ch->fsm, CTC_EVENT_IO_EBUSY, ch);201 break;202 case -ENODEV:203 pr_err("%s: The specified target device is not valid\n",204 ch->id);205 fsm_event(ch->fsm, CTC_EVENT_IO_ENODEV, ch);206 break;207 default:208 pr_err("An I/O operation resulted in error %04x\n",209 rc);210 fsm_event(ch->fsm, CTC_EVENT_IO_UNKNOWN, ch);211 }212}213 214void ctcm_purge_skb_queue(struct sk_buff_head *q)215{216 struct sk_buff *skb;217 218 CTCM_DBF_TEXT(TRACE, CTC_DBF_DEBUG, __func__);219 220 while ((skb = skb_dequeue(q))) {221 refcount_dec(&skb->users);222 dev_kfree_skb_any(skb);223 }224}225 226/*227 * NOP action for statemachines228 */229static void ctcm_action_nop(fsm_instance *fi, int event, void *arg)230{231}232 233/*234 * Actions for channel - statemachines.235 */236 237/*238 * Normal data has been send. Free the corresponding239 * skb (it's in io_queue), reset dev->tbusy and240 * revert to idle state.241 *242 * fi An instance of a channel statemachine.243 * event The event, just happened.244 * arg Generic pointer, casted from channel * upon call.245 */246static void chx_txdone(fsm_instance *fi, int event, void *arg)247{248 struct channel *ch = arg;249 struct net_device *dev = ch->netdev;250 struct ctcm_priv *priv = dev->ml_priv;251 struct sk_buff *skb;252 int first = 1;253 int i;254 unsigned long duration;255 unsigned long done_stamp = jiffies;256 257 CTCM_PR_DEBUG("%s(%s): %s\n", __func__, ch->id, dev->name);258 259 duration = done_stamp - ch->prof.send_stamp;260 if (duration > ch->prof.tx_time)261 ch->prof.tx_time = duration;262 263 if (ch->irb->scsw.cmd.count != 0)264 CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,265 "%s(%s): TX not complete, remaining %d bytes",266 CTCM_FUNTAIL, dev->name, ch->irb->scsw.cmd.count);267 fsm_deltimer(&ch->timer);268 while ((skb = skb_dequeue(&ch->io_queue))) {269 priv->stats.tx_packets++;270 priv->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;271 if (first) {272 priv->stats.tx_bytes += 2;273 first = 0;274 }275 refcount_dec(&skb->users);276 dev_kfree_skb_irq(skb);277 }278 spin_lock(&ch->collect_lock);279 clear_normalized_cda(&ch->ccw[4]);280 if (ch->collect_len > 0) {281 int rc;282 283 if (ctcm_checkalloc_buffer(ch)) {284 spin_unlock(&ch->collect_lock);285 return;286 }287 ch->trans_skb->data = ch->trans_skb_data;288 skb_reset_tail_pointer(ch->trans_skb);289 ch->trans_skb->len = 0;290 if (ch->prof.maxmulti < (ch->collect_len + 2))291 ch->prof.maxmulti = ch->collect_len + 2;292 if (ch->prof.maxcqueue < skb_queue_len(&ch->collect_queue))293 ch->prof.maxcqueue = skb_queue_len(&ch->collect_queue);294 *((__u16 *)skb_put(ch->trans_skb, 2)) = ch->collect_len + 2;295 i = 0;296 while ((skb = skb_dequeue(&ch->collect_queue))) {297 skb_copy_from_linear_data(skb,298 skb_put(ch->trans_skb, skb->len), skb->len);299 priv->stats.tx_packets++;300 priv->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;301 refcount_dec(&skb->users);302 dev_kfree_skb_irq(skb);303 i++;304 }305 ch->collect_len = 0;306 spin_unlock(&ch->collect_lock);307 ch->ccw[1].count = ch->trans_skb->len;308 fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);309 ch->prof.send_stamp = jiffies;310 rc = ccw_device_start(ch->cdev, &ch->ccw[0], 0, 0xff, 0);311 ch->prof.doios_multi++;312 if (rc != 0) {313 priv->stats.tx_dropped += i;314 priv->stats.tx_errors += i;315 fsm_deltimer(&ch->timer);316 ctcm_ccw_check_rc(ch, rc, "chained TX");317 }318 } else {319 spin_unlock(&ch->collect_lock);320 fsm_newstate(fi, CTC_STATE_TXIDLE);321 }322 ctcm_clear_busy_do(dev);323}324 325/*326 * Initial data is sent.327 * Notify device statemachine that we are up and328 * running.329 *330 * fi An instance of a channel statemachine.331 * event The event, just happened.332 * arg Generic pointer, casted from channel * upon call.333 */334void ctcm_chx_txidle(fsm_instance *fi, int event, void *arg)335{336 struct channel *ch = arg;337 struct net_device *dev = ch->netdev;338 struct ctcm_priv *priv = dev->ml_priv;339 340 CTCM_PR_DEBUG("%s(%s): %s\n", __func__, ch->id, dev->name);341 342 fsm_deltimer(&ch->timer);343 fsm_newstate(fi, CTC_STATE_TXIDLE);344 fsm_event(priv->fsm, DEV_EVENT_TXUP, ch->netdev);345}346 347/*348 * Got normal data, check for sanity, queue it up, allocate new buffer349 * trigger bottom half, and initiate next read.350 *351 * fi An instance of a channel statemachine.352 * event The event, just happened.353 * arg Generic pointer, casted from channel * upon call.354 */355static void chx_rx(fsm_instance *fi, int event, void *arg)356{357 struct channel *ch = arg;358 struct net_device *dev = ch->netdev;359 struct ctcm_priv *priv = dev->ml_priv;360 int len = ch->max_bufsize - ch->irb->scsw.cmd.count;361 struct sk_buff *skb = ch->trans_skb;362 __u16 block_len = *((__u16 *)skb->data);363 int check_len;364 int rc;365 366 fsm_deltimer(&ch->timer);367 if (len < 8) {368 CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,369 "%s(%s): got packet with length %d < 8\n",370 CTCM_FUNTAIL, dev->name, len);371 priv->stats.rx_dropped++;372 priv->stats.rx_length_errors++;373 goto again;374 }375 if (len > ch->max_bufsize) {376 CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,377 "%s(%s): got packet with length %d > %d\n",378 CTCM_FUNTAIL, dev->name, len, ch->max_bufsize);379 priv->stats.rx_dropped++;380 priv->stats.rx_length_errors++;381 goto again;382 }383 384 /*385 * VM TCP seems to have a bug sending 2 trailing bytes of garbage.386 */387 switch (ch->protocol) {388 case CTCM_PROTO_S390:389 case CTCM_PROTO_OS390:390 check_len = block_len + 2;391 break;392 default:393 check_len = block_len;394 break;395 }396 if ((len < block_len) || (len > check_len)) {397 CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,398 "%s(%s): got block length %d != rx length %d\n",399 CTCM_FUNTAIL, dev->name, block_len, len);400 if (do_debug)401 ctcmpc_dump_skb(skb, 0);402 403 *((__u16 *)skb->data) = len;404 priv->stats.rx_dropped++;405 priv->stats.rx_length_errors++;406 goto again;407 }408 if (block_len > 2) {409 *((__u16 *)skb->data) = block_len - 2;410 ctcm_unpack_skb(ch, skb);411 }412 again:413 skb->data = ch->trans_skb_data;414 skb_reset_tail_pointer(skb);415 skb->len = 0;416 if (ctcm_checkalloc_buffer(ch))417 return;418 ch->ccw[1].count = ch->max_bufsize;419 rc = ccw_device_start(ch->cdev, &ch->ccw[0], 0, 0xff, 0);420 if (rc != 0)421 ctcm_ccw_check_rc(ch, rc, "normal RX");422}423 424/*425 * Initialize connection by sending a __u16 of value 0.426 *427 * fi An instance of a channel statemachine.428 * event The event, just happened.429 * arg Generic pointer, casted from channel * upon call.430 */431static void chx_firstio(fsm_instance *fi, int event, void *arg)432{433 int rc;434 struct channel *ch = arg;435 int fsmstate = fsm_getstate(fi);436 437 CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,438 "%s(%s) : %02x",439 CTCM_FUNTAIL, ch->id, fsmstate);440 441 ch->sense_rc = 0; /* reset unit check report control */442 if (fsmstate == CTC_STATE_TXIDLE)443 CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,444 "%s(%s): remote side issued READ?, init.\n",445 CTCM_FUNTAIL, ch->id);446 fsm_deltimer(&ch->timer);447 if (ctcm_checkalloc_buffer(ch))448 return;449 if ((fsmstate == CTC_STATE_SETUPWAIT) &&450 (ch->protocol == CTCM_PROTO_OS390)) {451 /* OS/390 resp. z/OS */452 if (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) {453 *((__u16 *)ch->trans_skb->data) = CTCM_INITIAL_BLOCKLEN;454 fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC,455 CTC_EVENT_TIMER, ch);456 chx_rxidle(fi, event, arg);457 } else {458 struct net_device *dev = ch->netdev;459 struct ctcm_priv *priv = dev->ml_priv;460 fsm_newstate(fi, CTC_STATE_TXIDLE);461 fsm_event(priv->fsm, DEV_EVENT_TXUP, dev);462 }463 return;464 }465 /*466 * Don't setup a timer for receiving the initial RX frame467 * if in compatibility mode, since VM TCP delays the initial468 * frame until it has some data to send.469 */470 if ((CHANNEL_DIRECTION(ch->flags) == CTCM_WRITE) ||471 (ch->protocol != CTCM_PROTO_S390))472 fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);473 474 *((__u16 *)ch->trans_skb->data) = CTCM_INITIAL_BLOCKLEN;475 ch->ccw[1].count = 2; /* Transfer only length */476 477 fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == CTCM_READ)478 ? CTC_STATE_RXINIT : CTC_STATE_TXINIT);479 rc = ccw_device_start(ch->cdev, &ch->ccw[0], 0, 0xff, 0);480 if (rc != 0) {481 fsm_deltimer(&ch->timer);482 fsm_newstate(fi, CTC_STATE_SETUPWAIT);483 ctcm_ccw_check_rc(ch, rc, "init IO");484 }485 /*486 * If in compatibility mode since we don't setup a timer, we487 * also signal RX channel up immediately. This enables us488 * to send packets early which in turn usually triggers some489 * reply from VM TCP which brings up the RX channel to it's490 * final state.491 */492 if ((CHANNEL_DIRECTION(ch->flags) == CTCM_READ) &&493 (ch->protocol == CTCM_PROTO_S390)) {494 struct net_device *dev = ch->netdev;495 struct ctcm_priv *priv = dev->ml_priv;496 fsm_event(priv->fsm, DEV_EVENT_RXUP, dev);497 }498}499 500/*501 * Got initial data, check it. If OK,502 * notify device statemachine that we are up and503 * running.504 *505 * fi An instance of a channel statemachine.506 * event The event, just happened.507 * arg Generic pointer, casted from channel * upon call.508 */509static void chx_rxidle(fsm_instance *fi, int event, void *arg)510{511 struct channel *ch = arg;512 struct net_device *dev = ch->netdev;513 struct ctcm_priv *priv = dev->ml_priv;514 __u16 buflen;515 int rc;516 517 fsm_deltimer(&ch->timer);518 buflen = *((__u16 *)ch->trans_skb->data);519 CTCM_PR_DEBUG("%s: %s: Initial RX count = %d\n",520 __func__, dev->name, buflen);521 522 if (buflen >= CTCM_INITIAL_BLOCKLEN) {523 if (ctcm_checkalloc_buffer(ch))524 return;525 ch->ccw[1].count = ch->max_bufsize;526 fsm_newstate(fi, CTC_STATE_RXIDLE);527 rc = ccw_device_start(ch->cdev, &ch->ccw[0], 0, 0xff, 0);528 if (rc != 0) {529 fsm_newstate(fi, CTC_STATE_RXINIT);530 ctcm_ccw_check_rc(ch, rc, "initial RX");531 } else532 fsm_event(priv->fsm, DEV_EVENT_RXUP, dev);533 } else {534 CTCM_PR_DEBUG("%s: %s: Initial RX count %d not %d\n",535 __func__, dev->name,536 buflen, CTCM_INITIAL_BLOCKLEN);537 chx_firstio(fi, event, arg);538 }539}540 541/*542 * Set channel into extended mode.543 *544 * fi An instance of a channel statemachine.545 * event The event, just happened.546 * arg Generic pointer, casted from channel * upon call.547 */548static void ctcm_chx_setmode(fsm_instance *fi, int event, void *arg)549{550 struct channel *ch = arg;551 int rc;552 unsigned long saveflags = 0;553 int timeout = CTCM_TIME_5_SEC;554 555 fsm_deltimer(&ch->timer);556 if (IS_MPC(ch)) {557 timeout = 1500;558 CTCM_PR_DEBUG("enter %s: cp=%i ch=0x%p id=%s\n",559 __func__, smp_processor_id(), ch, ch->id);560 }561 fsm_addtimer(&ch->timer, timeout, CTC_EVENT_TIMER, ch);562 fsm_newstate(fi, CTC_STATE_SETUPWAIT);563 CTCM_CCW_DUMP((char *)&ch->ccw[6], sizeof(struct ccw1) * 2);564 565 if (event == CTC_EVENT_TIMER) /* only for timer not yet locked */566 spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);567 /* Such conditional locking is undeterministic in568 * static view. => ignore sparse warnings here. */569 570 rc = ccw_device_start(ch->cdev, &ch->ccw[6], 0, 0xff, 0);571 if (event == CTC_EVENT_TIMER) /* see above comments */572 spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);573 if (rc != 0) {574 fsm_deltimer(&ch->timer);575 fsm_newstate(fi, CTC_STATE_STARTWAIT);576 ctcm_ccw_check_rc(ch, rc, "set Mode");577 } else578 ch->retry = 0;579}580 581/*582 * Setup channel.583 *584 * fi An instance of a channel statemachine.585 * event The event, just happened.586 * arg Generic pointer, casted from channel * upon call.587 */588static void ctcm_chx_start(fsm_instance *fi, int event, void *arg)589{590 struct channel *ch = arg;591 unsigned long saveflags;592 int rc;593 594 CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s(%s): %s",595 CTCM_FUNTAIL, ch->id,596 (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) ? "RX" : "TX");597 598 if (ch->trans_skb != NULL) {599 clear_normalized_cda(&ch->ccw[1]);600 dev_kfree_skb(ch->trans_skb);601 ch->trans_skb = NULL;602 }603 if (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) {604 ch->ccw[1].cmd_code = CCW_CMD_READ;605 ch->ccw[1].flags = CCW_FLAG_SLI;606 ch->ccw[1].count = 0;607 } else {608 ch->ccw[1].cmd_code = CCW_CMD_WRITE;609 ch->ccw[1].flags = CCW_FLAG_SLI | CCW_FLAG_CC;610 ch->ccw[1].count = 0;611 }612 if (ctcm_checkalloc_buffer(ch)) {613 CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,614 "%s(%s): %s trans_skb alloc delayed "615 "until first transfer",616 CTCM_FUNTAIL, ch->id,617 (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) ?618 "RX" : "TX");619 }620 ch->ccw[0].cmd_code = CCW_CMD_PREPARE;621 ch->ccw[0].flags = CCW_FLAG_SLI | CCW_FLAG_CC;622 ch->ccw[0].count = 0;623 ch->ccw[0].cda = 0;624 ch->ccw[2].cmd_code = CCW_CMD_NOOP; /* jointed CE + DE */625 ch->ccw[2].flags = CCW_FLAG_SLI;626 ch->ccw[2].count = 0;627 ch->ccw[2].cda = 0;628 memcpy(&ch->ccw[3], &ch->ccw[0], sizeof(struct ccw1) * 3);629 ch->ccw[4].cda = 0;630 ch->ccw[4].flags &= ~CCW_FLAG_IDA;631 632 fsm_newstate(fi, CTC_STATE_STARTWAIT);633 fsm_addtimer(&ch->timer, 1000, CTC_EVENT_TIMER, ch);634 spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);635 rc = ccw_device_halt(ch->cdev, 0);636 spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);637 if (rc != 0) {638 if (rc != -EBUSY)639 fsm_deltimer(&ch->timer);640 ctcm_ccw_check_rc(ch, rc, "initial HaltIO");641 }642}643 644/*645 * Shutdown a channel.646 *647 * fi An instance of a channel statemachine.648 * event The event, just happened.649 * arg Generic pointer, casted from channel * upon call.650 */651static void ctcm_chx_haltio(fsm_instance *fi, int event, void *arg)652{653 struct channel *ch = arg;654 unsigned long saveflags = 0;655 int rc;656 int oldstate;657 658 fsm_deltimer(&ch->timer);659 if (IS_MPC(ch))660 fsm_deltimer(&ch->sweep_timer);661 662 fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);663 664 if (event == CTC_EVENT_STOP) /* only for STOP not yet locked */665 spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);666 /* Such conditional locking is undeterministic in667 * static view. => ignore sparse warnings here. */668 oldstate = fsm_getstate(fi);669 fsm_newstate(fi, CTC_STATE_TERM);670 rc = ccw_device_halt(ch->cdev, 0);671 672 if (event == CTC_EVENT_STOP)673 spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);674 /* see remark above about conditional locking */675 676 if (rc != 0 && rc != -EBUSY) {677 fsm_deltimer(&ch->timer);678 if (event != CTC_EVENT_STOP) {679 fsm_newstate(fi, oldstate);680 ctcm_ccw_check_rc(ch, rc, (char *)__func__);681 }682 }683}684 685/*686 * Cleanup helper for chx_fail and chx_stopped687 * cleanup channels queue and notify interface statemachine.688 *689 * fi An instance of a channel statemachine.690 * state The next state (depending on caller).691 * ch The channel to operate on.692 */693static void ctcm_chx_cleanup(fsm_instance *fi, int state,694 struct channel *ch)695{696 struct net_device *dev = ch->netdev;697 struct ctcm_priv *priv = dev->ml_priv;698 699 CTCM_DBF_TEXT_(SETUP, CTC_DBF_NOTICE,700 "%s(%s): %s[%d]\n",701 CTCM_FUNTAIL, dev->name, ch->id, state);702 703 fsm_deltimer(&ch->timer);704 if (IS_MPC(ch))705 fsm_deltimer(&ch->sweep_timer);706 707 fsm_newstate(fi, state);708 if (state == CTC_STATE_STOPPED && ch->trans_skb != NULL) {709 clear_normalized_cda(&ch->ccw[1]);710 dev_kfree_skb_any(ch->trans_skb);711 ch->trans_skb = NULL;712 }713 714 ch->th_seg = 0x00;715 ch->th_seq_num = 0x00;716 if (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) {717 skb_queue_purge(&ch->io_queue);718 fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);719 } else {720 ctcm_purge_skb_queue(&ch->io_queue);721 if (IS_MPC(ch))722 ctcm_purge_skb_queue(&ch->sweep_queue);723 spin_lock(&ch->collect_lock);724 ctcm_purge_skb_queue(&ch->collect_queue);725 ch->collect_len = 0;726 spin_unlock(&ch->collect_lock);727 fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);728 }729}730 731/*732 * A channel has successfully been halted.733 * Cleanup it's queue and notify interface statemachine.734 *735 * fi An instance of a channel statemachine.736 * event The event, just happened.737 * arg Generic pointer, casted from channel * upon call.738 */739static void ctcm_chx_stopped(fsm_instance *fi, int event, void *arg)740{741 ctcm_chx_cleanup(fi, CTC_STATE_STOPPED, arg);742}743 744/*745 * A stop command from device statemachine arrived and we are in746 * not operational mode. Set state to stopped.747 *748 * fi An instance of a channel statemachine.749 * event The event, just happened.750 * arg Generic pointer, casted from channel * upon call.751 */752static void ctcm_chx_stop(fsm_instance *fi, int event, void *arg)753{754 fsm_newstate(fi, CTC_STATE_STOPPED);755}756 757/*758 * A machine check for no path, not operational status or gone device has759 * happened.760 * Cleanup queue and notify interface statemachine.761 *762 * fi An instance of a channel statemachine.763 * event The event, just happened.764 * arg Generic pointer, casted from channel * upon call.765 */766static void ctcm_chx_fail(fsm_instance *fi, int event, void *arg)767{768 ctcm_chx_cleanup(fi, CTC_STATE_NOTOP, arg);769}770 771/*772 * Handle error during setup of channel.773 *774 * fi An instance of a channel statemachine.775 * event The event, just happened.776 * arg Generic pointer, casted from channel * upon call.777 */778static void ctcm_chx_setuperr(fsm_instance *fi, int event, void *arg)779{780 struct channel *ch = arg;781 struct net_device *dev = ch->netdev;782 struct ctcm_priv *priv = dev->ml_priv;783 784 /*785 * Special case: Got UC_RCRESET on setmode.786 * This means that remote side isn't setup. In this case787 * simply retry after some 10 secs...788 */789 if ((fsm_getstate(fi) == CTC_STATE_SETUPWAIT) &&790 ((event == CTC_EVENT_UC_RCRESET) ||791 (event == CTC_EVENT_UC_RSRESET))) {792 fsm_newstate(fi, CTC_STATE_STARTRETRY);793 fsm_deltimer(&ch->timer);794 fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);795 if (!IS_MPC(ch) &&796 (CHANNEL_DIRECTION(ch->flags) == CTCM_READ)) {797 int rc = ccw_device_halt(ch->cdev, 0);798 if (rc != 0)799 ctcm_ccw_check_rc(ch, rc,800 "HaltIO in chx_setuperr");801 }802 return;803 }804 805 CTCM_DBF_TEXT_(ERROR, CTC_DBF_CRIT,806 "%s(%s) : %s error during %s channel setup state=%s\n",807 CTCM_FUNTAIL, dev->name, ctc_ch_event_names[event],808 (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) ? "RX" : "TX",809 fsm_getstate_str(fi));810 811 if (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) {812 fsm_newstate(fi, CTC_STATE_RXERR);813 fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);814 } else {815 fsm_newstate(fi, CTC_STATE_TXERR);816 fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);817 }818}819 820/*821 * Restart a channel after an error.822 *823 * fi An instance of a channel statemachine.824 * event The event, just happened.825 * arg Generic pointer, casted from channel * upon call.826 */827static void ctcm_chx_restart(fsm_instance *fi, int event, void *arg)828{829 struct channel *ch = arg;830 struct net_device *dev = ch->netdev;831 unsigned long saveflags = 0;832 int oldstate;833 int rc;834 835 CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,836 "%s: %s[%d] of %s\n",837 CTCM_FUNTAIL, ch->id, event, dev->name);838 839 fsm_deltimer(&ch->timer);840 841 fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);842 oldstate = fsm_getstate(fi);843 fsm_newstate(fi, CTC_STATE_STARTWAIT);844 if (event == CTC_EVENT_TIMER) /* only for timer not yet locked */845 spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);846 /* Such conditional locking is a known problem for847 * sparse because its undeterministic in static view.848 * Warnings should be ignored here. */849 rc = ccw_device_halt(ch->cdev, 0);850 if (event == CTC_EVENT_TIMER)851 spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);852 if (rc != 0) {853 if (rc != -EBUSY) {854 fsm_deltimer(&ch->timer);855 fsm_newstate(fi, oldstate);856 }857 ctcm_ccw_check_rc(ch, rc, "HaltIO in ctcm_chx_restart");858 }859}860 861/*862 * Handle error during RX initial handshake (exchange of863 * 0-length block header)864 *865 * fi An instance of a channel statemachine.866 * event The event, just happened.867 * arg Generic pointer, casted from channel * upon call.868 */869static void ctcm_chx_rxiniterr(fsm_instance *fi, int event, void *arg)870{871 struct channel *ch = arg;872 struct net_device *dev = ch->netdev;873 struct ctcm_priv *priv = dev->ml_priv;874 875 if (event == CTC_EVENT_TIMER) {876 if (!IS_MPCDEV(dev))877 /* TODO : check if MPC deletes timer somewhere */878 fsm_deltimer(&ch->timer);879 if (ch->retry++ < 3)880 ctcm_chx_restart(fi, event, arg);881 else {882 fsm_newstate(fi, CTC_STATE_RXERR);883 fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);884 }885 } else {886 CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,887 "%s(%s): %s in %s", CTCM_FUNTAIL, ch->id,888 ctc_ch_event_names[event], fsm_getstate_str(fi));889 890 dev_warn(&dev->dev,891 "Initialization failed with RX/TX init handshake "892 "error %s\n", ctc_ch_event_names[event]);893 }894}895 896/*897 * Notify device statemachine if we gave up initialization898 * of RX channel.899 *900 * fi An instance of a channel statemachine.901 * event The event, just happened.902 * arg Generic pointer, casted from channel * upon call.903 */904static void ctcm_chx_rxinitfail(fsm_instance *fi, int event, void *arg)905{906 struct channel *ch = arg;907 struct net_device *dev = ch->netdev;908 struct ctcm_priv *priv = dev->ml_priv;909 910 CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,911 "%s(%s): RX %s busy, init. fail",912 CTCM_FUNTAIL, dev->name, ch->id);913 fsm_newstate(fi, CTC_STATE_RXERR);914 fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);915}916 917/*918 * Handle RX Unit check remote reset (remote disconnected)919 *920 * fi An instance of a channel statemachine.921 * event The event, just happened.922 * arg Generic pointer, casted from channel * upon call.923 */924static void ctcm_chx_rxdisc(fsm_instance *fi, int event, void *arg)925{926 struct channel *ch = arg;927 struct channel *ch2;928 struct net_device *dev = ch->netdev;929 struct ctcm_priv *priv = dev->ml_priv;930 931 CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,932 "%s: %s: remote disconnect - re-init ...",933 CTCM_FUNTAIL, dev->name);934 fsm_deltimer(&ch->timer);935 /*936 * Notify device statemachine937 */938 fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);939 fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);940 941 fsm_newstate(fi, CTC_STATE_DTERM);942 ch2 = priv->channel[CTCM_WRITE];943 fsm_newstate(ch2->fsm, CTC_STATE_DTERM);944 945 ccw_device_halt(ch->cdev, 0);946 ccw_device_halt(ch2->cdev, 0);947}948 949/*950 * Handle error during TX channel initialization.951 *952 * fi An instance of a channel statemachine.953 * event The event, just happened.954 * arg Generic pointer, casted from channel * upon call.955 */956static void ctcm_chx_txiniterr(fsm_instance *fi, int event, void *arg)957{958 struct channel *ch = arg;959 struct net_device *dev = ch->netdev;960 struct ctcm_priv *priv = dev->ml_priv;961 962 if (event == CTC_EVENT_TIMER) {963 fsm_deltimer(&ch->timer);964 if (ch->retry++ < 3)965 ctcm_chx_restart(fi, event, arg);966 else {967 fsm_newstate(fi, CTC_STATE_TXERR);968 fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);969 }970 } else {971 CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,972 "%s(%s): %s in %s", CTCM_FUNTAIL, ch->id,973 ctc_ch_event_names[event], fsm_getstate_str(fi));974 975 dev_warn(&dev->dev,976 "Initialization failed with RX/TX init handshake "977 "error %s\n", ctc_ch_event_names[event]);978 }979}980 981/*982 * Handle TX timeout by retrying operation.983 *984 * fi An instance of a channel statemachine.985 * event The event, just happened.986 * arg Generic pointer, casted from channel * upon call.987 */988static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg)989{990 struct channel *ch = arg;991 struct net_device *dev = ch->netdev;992 struct ctcm_priv *priv = dev->ml_priv;993 struct sk_buff *skb;994 995 CTCM_PR_DEBUG("Enter: %s: cp=%i ch=0x%p id=%s\n",996 __func__, smp_processor_id(), ch, ch->id);997 998 fsm_deltimer(&ch->timer);999 if (ch->retry++ > 3) {1000 struct mpc_group *gptr = priv->mpcg;1001 CTCM_DBF_TEXT_(TRACE, CTC_DBF_INFO,1002 "%s: %s: retries exceeded",1003 CTCM_FUNTAIL, ch->id);1004 fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);1005 /* call restart if not MPC or if MPC and mpcg fsm is ready.1006 use gptr as mpc indicator */1007 if (!(gptr && (fsm_getstate(gptr->fsm) != MPCG_STATE_READY)))1008 ctcm_chx_restart(fi, event, arg);1009 goto done;1010 }1011 1012 CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,1013 "%s : %s: retry %d",1014 CTCM_FUNTAIL, ch->id, ch->retry);1015 skb = skb_peek(&ch->io_queue);1016 if (skb) {1017 int rc = 0;1018 unsigned long saveflags = 0;1019 clear_normalized_cda(&ch->ccw[4]);1020 ch->ccw[4].count = skb->len;1021 if (set_normalized_cda(&ch->ccw[4], skb->data)) {1022 CTCM_DBF_TEXT_(TRACE, CTC_DBF_INFO,1023 "%s: %s: IDAL alloc failed",1024 CTCM_FUNTAIL, ch->id);1025 fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);1026 ctcm_chx_restart(fi, event, arg);1027 goto done;1028 }1029 fsm_addtimer(&ch->timer, 1000, CTC_EVENT_TIMER, ch);1030 if (event == CTC_EVENT_TIMER) /* for TIMER not yet locked */1031 spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);1032 /* Such conditional locking is a known problem for1033 * sparse because its undeterministic in static view.1034 * Warnings should be ignored here. */1035 if (do_debug_ccw)1036 ctcmpc_dumpit((char *)&ch->ccw[3],1037 sizeof(struct ccw1) * 3);1038 1039 rc = ccw_device_start(ch->cdev, &ch->ccw[3], 0, 0xff, 0);1040 if (event == CTC_EVENT_TIMER)1041 spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev),1042 saveflags);1043 if (rc != 0) {1044 fsm_deltimer(&ch->timer);1045 ctcm_ccw_check_rc(ch, rc, "TX in chx_txretry");1046 ctcm_purge_skb_queue(&ch->io_queue);1047 }1048 }1049done:1050 return;1051}1052 1053/*1054 * Handle fatal errors during an I/O command.1055 *1056 * fi An instance of a channel statemachine.1057 * event The event, just happened.1058 * arg Generic pointer, casted from channel * upon call.1059 */1060static void ctcm_chx_iofatal(fsm_instance *fi, int event, void *arg)1061{1062 struct channel *ch = arg;1063 struct net_device *dev = ch->netdev;1064 struct ctcm_priv *priv = dev->ml_priv;1065 int rd = CHANNEL_DIRECTION(ch->flags);1066 1067 fsm_deltimer(&ch->timer);1068 CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,1069 "%s: %s: %s unrecoverable channel error",1070 CTCM_FUNTAIL, ch->id, rd == CTCM_READ ? "RX" : "TX");1071 1072 if (IS_MPC(ch)) {1073 priv->stats.tx_dropped++;1074 priv->stats.tx_errors++;1075 }1076 if (rd == CTCM_READ) {1077 fsm_newstate(fi, CTC_STATE_RXERR);1078 fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);1079 } else {1080 fsm_newstate(fi, CTC_STATE_TXERR);1081 fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);1082 }1083}1084 1085/*1086 * The ctcm statemachine for a channel.1087 */1088const fsm_node ch_fsm[] = {1089 { CTC_STATE_STOPPED, CTC_EVENT_STOP, ctcm_action_nop },1090 { CTC_STATE_STOPPED, CTC_EVENT_START, ctcm_chx_start },1091 { CTC_STATE_STOPPED, CTC_EVENT_FINSTAT, ctcm_action_nop },1092 { CTC_STATE_STOPPED, CTC_EVENT_MC_FAIL, ctcm_action_nop },1093 1094 { CTC_STATE_NOTOP, CTC_EVENT_STOP, ctcm_chx_stop },1095 { CTC_STATE_NOTOP, CTC_EVENT_START, ctcm_action_nop },1096 { CTC_STATE_NOTOP, CTC_EVENT_FINSTAT, ctcm_action_nop },1097 { CTC_STATE_NOTOP, CTC_EVENT_MC_FAIL, ctcm_action_nop },1098 { CTC_STATE_NOTOP, CTC_EVENT_MC_GOOD, ctcm_chx_start },1099 1100 { CTC_STATE_STARTWAIT, CTC_EVENT_STOP, ctcm_chx_haltio },1101 { CTC_STATE_STARTWAIT, CTC_EVENT_START, ctcm_action_nop },1102 { CTC_STATE_STARTWAIT, CTC_EVENT_FINSTAT, ctcm_chx_setmode },1103 { CTC_STATE_STARTWAIT, CTC_EVENT_TIMER, ctcm_chx_setuperr },1104 { CTC_STATE_STARTWAIT, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1105 { CTC_STATE_STARTWAIT, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1106 1107 { CTC_STATE_STARTRETRY, CTC_EVENT_STOP, ctcm_chx_haltio },1108 { CTC_STATE_STARTRETRY, CTC_EVENT_TIMER, ctcm_chx_setmode },1109 { CTC_STATE_STARTRETRY, CTC_EVENT_FINSTAT, ctcm_action_nop },1110 { CTC_STATE_STARTRETRY, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1111 1112 { CTC_STATE_SETUPWAIT, CTC_EVENT_STOP, ctcm_chx_haltio },1113 { CTC_STATE_SETUPWAIT, CTC_EVENT_START, ctcm_action_nop },1114 { CTC_STATE_SETUPWAIT, CTC_EVENT_FINSTAT, chx_firstio },1115 { CTC_STATE_SETUPWAIT, CTC_EVENT_UC_RCRESET, ctcm_chx_setuperr },1116 { CTC_STATE_SETUPWAIT, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },1117 { CTC_STATE_SETUPWAIT, CTC_EVENT_TIMER, ctcm_chx_setmode },1118 { CTC_STATE_SETUPWAIT, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1119 { CTC_STATE_SETUPWAIT, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1120 1121 { CTC_STATE_RXINIT, CTC_EVENT_STOP, ctcm_chx_haltio },1122 { CTC_STATE_RXINIT, CTC_EVENT_START, ctcm_action_nop },1123 { CTC_STATE_RXINIT, CTC_EVENT_FINSTAT, chx_rxidle },1124 { CTC_STATE_RXINIT, CTC_EVENT_UC_RCRESET, ctcm_chx_rxiniterr },1125 { CTC_STATE_RXINIT, CTC_EVENT_UC_RSRESET, ctcm_chx_rxiniterr },1126 { CTC_STATE_RXINIT, CTC_EVENT_TIMER, ctcm_chx_rxiniterr },1127 { CTC_STATE_RXINIT, CTC_EVENT_ATTNBUSY, ctcm_chx_rxinitfail },1128 { CTC_STATE_RXINIT, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1129 { CTC_STATE_RXINIT, CTC_EVENT_UC_ZERO, chx_firstio },1130 { CTC_STATE_RXINIT, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1131 1132 { CTC_STATE_RXIDLE, CTC_EVENT_STOP, ctcm_chx_haltio },1133 { CTC_STATE_RXIDLE, CTC_EVENT_START, ctcm_action_nop },1134 { CTC_STATE_RXIDLE, CTC_EVENT_FINSTAT, chx_rx },1135 { CTC_STATE_RXIDLE, CTC_EVENT_UC_RCRESET, ctcm_chx_rxdisc },1136 { CTC_STATE_RXIDLE, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1137 { CTC_STATE_RXIDLE, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1138 { CTC_STATE_RXIDLE, CTC_EVENT_UC_ZERO, chx_rx },1139 1140 { CTC_STATE_TXINIT, CTC_EVENT_STOP, ctcm_chx_haltio },1141 { CTC_STATE_TXINIT, CTC_EVENT_START, ctcm_action_nop },1142 { CTC_STATE_TXINIT, CTC_EVENT_FINSTAT, ctcm_chx_txidle },1143 { CTC_STATE_TXINIT, CTC_EVENT_UC_RCRESET, ctcm_chx_txiniterr },1144 { CTC_STATE_TXINIT, CTC_EVENT_UC_RSRESET, ctcm_chx_txiniterr },1145 { CTC_STATE_TXINIT, CTC_EVENT_TIMER, ctcm_chx_txiniterr },1146 { CTC_STATE_TXINIT, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1147 { CTC_STATE_TXINIT, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1148 1149 { CTC_STATE_TXIDLE, CTC_EVENT_STOP, ctcm_chx_haltio },1150 { CTC_STATE_TXIDLE, CTC_EVENT_START, ctcm_action_nop },1151 { CTC_STATE_TXIDLE, CTC_EVENT_FINSTAT, chx_firstio },1152 { CTC_STATE_TXIDLE, CTC_EVENT_UC_RCRESET, ctcm_action_nop },1153 { CTC_STATE_TXIDLE, CTC_EVENT_UC_RSRESET, ctcm_action_nop },1154 { CTC_STATE_TXIDLE, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1155 { CTC_STATE_TXIDLE, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1156 1157 { CTC_STATE_TERM, CTC_EVENT_STOP, ctcm_action_nop },1158 { CTC_STATE_TERM, CTC_EVENT_START, ctcm_chx_restart },1159 { CTC_STATE_TERM, CTC_EVENT_FINSTAT, ctcm_chx_stopped },1160 { CTC_STATE_TERM, CTC_EVENT_UC_RCRESET, ctcm_action_nop },1161 { CTC_STATE_TERM, CTC_EVENT_UC_RSRESET, ctcm_action_nop },1162 { CTC_STATE_TERM, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1163 1164 { CTC_STATE_DTERM, CTC_EVENT_STOP, ctcm_chx_haltio },1165 { CTC_STATE_DTERM, CTC_EVENT_START, ctcm_chx_restart },1166 { CTC_STATE_DTERM, CTC_EVENT_FINSTAT, ctcm_chx_setmode },1167 { CTC_STATE_DTERM, CTC_EVENT_UC_RCRESET, ctcm_action_nop },1168 { CTC_STATE_DTERM, CTC_EVENT_UC_RSRESET, ctcm_action_nop },1169 { CTC_STATE_DTERM, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1170 1171 { CTC_STATE_TX, CTC_EVENT_STOP, ctcm_chx_haltio },1172 { CTC_STATE_TX, CTC_EVENT_START, ctcm_action_nop },1173 { CTC_STATE_TX, CTC_EVENT_FINSTAT, chx_txdone },1174 { CTC_STATE_TX, CTC_EVENT_UC_RCRESET, ctcm_chx_txretry },1175 { CTC_STATE_TX, CTC_EVENT_UC_RSRESET, ctcm_chx_txretry },1176 { CTC_STATE_TX, CTC_EVENT_TIMER, ctcm_chx_txretry },1177 { CTC_STATE_TX, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1178 { CTC_STATE_TX, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1179 1180 { CTC_STATE_RXERR, CTC_EVENT_STOP, ctcm_chx_haltio },1181 { CTC_STATE_TXERR, CTC_EVENT_STOP, ctcm_chx_haltio },1182 { CTC_STATE_TXERR, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1183 { CTC_STATE_RXERR, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1184};1185 1186int ch_fsm_len = ARRAY_SIZE(ch_fsm);1187 1188/*1189 * MPC actions for mpc channel statemachine1190 * handling of MPC protocol requires extra1191 * statemachine and actions which are prefixed ctcmpc_ .1192 * The ctc_ch_states and ctc_ch_state_names,1193 * ctc_ch_events and ctc_ch_event_names share the ctcm definitions1194 * which are expanded by some elements.1195 */1196 1197/*1198 * Actions for mpc channel statemachine.1199 */1200 1201/*1202 * Normal data has been send. Free the corresponding1203 * skb (it's in io_queue), reset dev->tbusy and1204 * revert to idle state.1205 *1206 * fi An instance of a channel statemachine.1207 * event The event, just happened.1208 * arg Generic pointer, casted from channel * upon call.1209 */1210static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)1211{1212 struct channel *ch = arg;1213 struct net_device *dev = ch->netdev;1214 struct ctcm_priv *priv = dev->ml_priv;1215 struct mpc_group *grp = priv->mpcg;1216 struct sk_buff *skb;1217 int first = 1;1218 int i;1219 __u32 data_space;1220 unsigned long duration;1221 struct sk_buff *peekskb;1222 int rc;1223 struct th_header *header;1224 struct pdu *p_header;1225 unsigned long done_stamp = jiffies;1226 1227 CTCM_PR_DEBUG("Enter %s: %s cp:%i\n",1228 __func__, dev->name, smp_processor_id());1229 1230 duration = done_stamp - ch->prof.send_stamp;1231 if (duration > ch->prof.tx_time)1232 ch->prof.tx_time = duration;1233 1234 if (ch->irb->scsw.cmd.count != 0)1235 CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,1236 "%s(%s): TX not complete, remaining %d bytes",1237 CTCM_FUNTAIL, dev->name, ch->irb->scsw.cmd.count);1238 fsm_deltimer(&ch->timer);1239 while ((skb = skb_dequeue(&ch->io_queue))) {1240 priv->stats.tx_packets++;1241 priv->stats.tx_bytes += skb->len - TH_HEADER_LENGTH;1242 if (first) {1243 priv->stats.tx_bytes += 2;1244 first = 0;1245 }1246 refcount_dec(&skb->users);1247 dev_kfree_skb_irq(skb);1248 }1249 spin_lock(&ch->collect_lock);1250 clear_normalized_cda(&ch->ccw[4]);1251 if ((ch->collect_len <= 0) || (grp->in_sweep != 0)) {1252 spin_unlock(&ch->collect_lock);1253 fsm_newstate(fi, CTC_STATE_TXIDLE);1254 goto done;1255 }1256 1257 if (ctcm_checkalloc_buffer(ch)) {1258 spin_unlock(&ch->collect_lock);1259 goto done;1260 }1261 ch->trans_skb->data = ch->trans_skb_data;1262 skb_reset_tail_pointer(ch->trans_skb);1263 ch->trans_skb->len = 0;1264 if (ch->prof.maxmulti < (ch->collect_len + TH_HEADER_LENGTH))1265 ch->prof.maxmulti = ch->collect_len + TH_HEADER_LENGTH;1266 if (ch->prof.maxcqueue < skb_queue_len(&ch->collect_queue))1267 ch->prof.maxcqueue = skb_queue_len(&ch->collect_queue);1268 i = 0;1269 p_header = NULL;1270 data_space = grp->group_max_buflen - TH_HEADER_LENGTH;1271 1272 CTCM_PR_DBGDATA("%s: building trans_skb from collect_q"1273 " data_space:%04x\n",1274 __func__, data_space);1275 1276 while ((skb = skb_dequeue(&ch->collect_queue))) {1277 skb_put_data(ch->trans_skb, skb->data, skb->len);1278 p_header = (struct pdu *)1279 (skb_tail_pointer(ch->trans_skb) - skb->len);1280 p_header->pdu_flag = 0x00;1281 if (be16_to_cpu(skb->protocol) == ETH_P_SNAP)1282 p_header->pdu_flag |= 0x60;1283 else1284 p_header->pdu_flag |= 0x20;1285 1286 CTCM_PR_DBGDATA("%s: trans_skb len:%04x \n",1287 __func__, ch->trans_skb->len);1288 CTCM_PR_DBGDATA("%s: pdu header and data for up"1289 " to 32 bytes sent to vtam\n", __func__);1290 CTCM_D3_DUMP((char *)p_header, min_t(int, skb->len, 32));1291 1292 ch->collect_len -= skb->len;1293 data_space -= skb->len;1294 priv->stats.tx_packets++;1295 priv->stats.tx_bytes += skb->len;1296 refcount_dec(&skb->users);1297 dev_kfree_skb_any(skb);1298 peekskb = skb_peek(&ch->collect_queue);1299 if (peekskb->len > data_space)1300 break;1301 i++;1302 }1303 /* p_header points to the last one we handled */1304 if (p_header)1305 p_header->pdu_flag |= PDU_LAST; /*Say it's the last one*/1306 1307 header = skb_push(ch->trans_skb, TH_HEADER_LENGTH);1308 memset(header, 0, TH_HEADER_LENGTH);1309 1310 header->th_ch_flag = TH_HAS_PDU; /* Normal data */1311 ch->th_seq_num++;1312 header->th_seq_num = ch->th_seq_num;1313 1314 CTCM_PR_DBGDATA("%s: ToVTAM_th_seq= %08x\n" ,1315 __func__, ch->th_seq_num);1316 1317 CTCM_PR_DBGDATA("%s: trans_skb len:%04x \n",1318 __func__, ch->trans_skb->len);1319 CTCM_PR_DBGDATA("%s: up-to-50 bytes of trans_skb "1320 "data to vtam from collect_q\n", __func__);1321 CTCM_D3_DUMP((char *)ch->trans_skb->data,1322 min_t(int, ch->trans_skb->len, 50));1323 1324 spin_unlock(&ch->collect_lock);1325 clear_normalized_cda(&ch->ccw[1]);1326 1327 CTCM_PR_DBGDATA("ccwcda=0x%p data=0x%p\n",1328 (void *)(u64)dma32_to_u32(ch->ccw[1].cda),1329 ch->trans_skb->data);1330 ch->ccw[1].count = ch->max_bufsize;1331 1332 if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) {1333 dev_kfree_skb_any(ch->trans_skb);1334 ch->trans_skb = NULL;1335 CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ERROR,1336 "%s: %s: IDAL alloc failed",1337 CTCM_FUNTAIL, ch->id);1338 fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);1339 return;1340 }1341 1342 CTCM_PR_DBGDATA("ccwcda=0x%p data=0x%p\n",1343 (void *)(u64)dma32_to_u32(ch->ccw[1].cda),1344 ch->trans_skb->data);1345 1346 ch->ccw[1].count = ch->trans_skb->len;1347 fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);1348 ch->prof.send_stamp = jiffies;1349 if (do_debug_ccw)1350 ctcmpc_dumpit((char *)&ch->ccw[0], sizeof(struct ccw1) * 3);1351 rc = ccw_device_start(ch->cdev, &ch->ccw[0], 0, 0xff, 0);1352 ch->prof.doios_multi++;1353 if (rc != 0) {1354 priv->stats.tx_dropped += i;1355 priv->stats.tx_errors += i;1356 fsm_deltimer(&ch->timer);1357 ctcm_ccw_check_rc(ch, rc, "chained TX");1358 }1359done:1360 ctcm_clear_busy(dev);1361 return;1362}1363 1364/*1365 * Got normal data, check for sanity, queue it up, allocate new buffer1366 * trigger bottom half, and initiate next read.1367 *1368 * fi An instance of a channel statemachine.1369 * event The event, just happened.1370 * arg Generic pointer, casted from channel * upon call.1371 */1372static void ctcmpc_chx_rx(fsm_instance *fi, int event, void *arg)1373{1374 struct channel *ch = arg;1375 struct net_device *dev = ch->netdev;1376 struct ctcm_priv *priv = dev->ml_priv;1377 struct mpc_group *grp = priv->mpcg;1378 struct sk_buff *skb = ch->trans_skb;1379 struct sk_buff *new_skb;1380 unsigned long saveflags = 0; /* avoids compiler warning */1381 int len = ch->max_bufsize - ch->irb->scsw.cmd.count;1382 1383 CTCM_PR_DEBUG("%s: %s: cp:%i %s maxbuf : %04x, len: %04x\n",1384 CTCM_FUNTAIL, dev->name, smp_processor_id(),1385 ch->id, ch->max_bufsize, len);1386 fsm_deltimer(&ch->timer);1387 1388 if (skb == NULL) {1389 CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,1390 "%s(%s): TRANS_SKB = NULL",1391 CTCM_FUNTAIL, dev->name);1392 goto again;1393 }1394 1395 if (len < TH_HEADER_LENGTH) {1396 CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,1397 "%s(%s): packet length %d too short",1398 CTCM_FUNTAIL, dev->name, len);1399 priv->stats.rx_dropped++;1400 priv->stats.rx_length_errors++;1401 } else {1402 /* must have valid th header or game over */1403 __u32 block_len = len;1404 len = TH_HEADER_LENGTH + XID2_LENGTH + 4;1405 new_skb = __dev_alloc_skb(ch->max_bufsize, GFP_ATOMIC);1406 1407 if (new_skb == NULL) {1408 CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,1409 "%s(%s): skb allocation failed",1410 CTCM_FUNTAIL, dev->name);1411 fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);1412 goto again;1413 }1414 switch (fsm_getstate(grp->fsm)) {1415 case MPCG_STATE_RESET:1416 case MPCG_STATE_INOP:1417 dev_kfree_skb_any(new_skb);1418 break;1419 case MPCG_STATE_FLOWC:1420 case MPCG_STATE_READY:1421 skb_put_data(new_skb, skb->data, block_len);1422 skb_queue_tail(&ch->io_queue, new_skb);1423 tasklet_schedule(&ch->ch_tasklet);1424 break;1425 default:1426 skb_put_data(new_skb, skb->data, len);1427 skb_queue_tail(&ch->io_queue, new_skb);1428 tasklet_hi_schedule(&ch->ch_tasklet);1429 break;1430 }1431 }1432 1433again:1434 switch (fsm_getstate(grp->fsm)) {1435 int rc, dolock;1436 case MPCG_STATE_FLOWC:1437 case MPCG_STATE_READY:1438 if (ctcm_checkalloc_buffer(ch))1439 break;1440 ch->trans_skb->data = ch->trans_skb_data;1441 skb_reset_tail_pointer(ch->trans_skb);1442 ch->trans_skb->len = 0;1443 ch->ccw[1].count = ch->max_bufsize;1444 if (do_debug_ccw)1445 ctcmpc_dumpit((char *)&ch->ccw[0],1446 sizeof(struct ccw1) * 3);1447 dolock = !in_hardirq();1448 if (dolock)1449 spin_lock_irqsave(1450 get_ccwdev_lock(ch->cdev), saveflags);1451 rc = ccw_device_start(ch->cdev, &ch->ccw[0], 0, 0xff, 0);1452 if (dolock) /* see remark about conditional locking */1453 spin_unlock_irqrestore(1454 get_ccwdev_lock(ch->cdev), saveflags);1455 if (rc != 0)1456 ctcm_ccw_check_rc(ch, rc, "normal RX");1457 break;1458 default:1459 break;1460 }1461 1462 CTCM_PR_DEBUG("Exit %s: %s, ch=0x%p, id=%s\n",1463 __func__, dev->name, ch, ch->id);1464 1465}1466 1467/*1468 * Initialize connection by sending a __u16 of value 0.1469 *1470 * fi An instance of a channel statemachine.1471 * event The event, just happened.1472 * arg Generic pointer, casted from channel * upon call.1473 */1474static void ctcmpc_chx_firstio(fsm_instance *fi, int event, void *arg)1475{1476 struct channel *ch = arg;1477 struct net_device *dev = ch->netdev;1478 struct ctcm_priv *priv = dev->ml_priv;1479 struct mpc_group *gptr = priv->mpcg;1480 1481 CTCM_PR_DEBUG("Enter %s: id=%s, ch=0x%p\n",1482 __func__, ch->id, ch);1483 1484 CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_INFO,1485 "%s: %s: chstate:%i, grpstate:%i, prot:%i\n",1486 CTCM_FUNTAIL, ch->id, fsm_getstate(fi),1487 fsm_getstate(gptr->fsm), ch->protocol);1488 1489 if (fsm_getstate(fi) == CTC_STATE_TXIDLE)1490 MPC_DBF_DEV_NAME(TRACE, dev, "remote side issued READ? ");1491 1492 fsm_deltimer(&ch->timer);1493 if (ctcm_checkalloc_buffer(ch))1494 goto done;1495 1496 switch (fsm_getstate(fi)) {1497 case CTC_STATE_STARTRETRY:1498 case CTC_STATE_SETUPWAIT:1499 if (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) {1500 ctcmpc_chx_rxidle(fi, event, arg);1501 } else {1502 fsm_newstate(fi, CTC_STATE_TXIDLE);1503 fsm_event(priv->fsm, DEV_EVENT_TXUP, dev);1504 }1505 goto done;1506 default:1507 break;1508 }1509 1510 fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == CTCM_READ)1511 ? CTC_STATE_RXINIT : CTC_STATE_TXINIT);1512 1513done:1514 CTCM_PR_DEBUG("Exit %s: id=%s, ch=0x%p\n",1515 __func__, ch->id, ch);1516 return;1517}1518 1519/*1520 * Got initial data, check it. If OK,1521 * notify device statemachine that we are up and1522 * running.1523 *1524 * fi An instance of a channel statemachine.1525 * event The event, just happened.1526 * arg Generic pointer, casted from channel * upon call.1527 */1528void ctcmpc_chx_rxidle(fsm_instance *fi, int event, void *arg)1529{1530 struct channel *ch = arg;1531 struct net_device *dev = ch->netdev;1532 struct ctcm_priv *priv = dev->ml_priv;1533 struct mpc_group *grp = priv->mpcg;1534 int rc;1535 unsigned long saveflags = 0; /* avoids compiler warning */1536 1537 fsm_deltimer(&ch->timer);1538 CTCM_PR_DEBUG("%s: %s: %s: cp:%i, chstate:%i grpstate:%i\n",1539 __func__, ch->id, dev->name, smp_processor_id(),1540 fsm_getstate(fi), fsm_getstate(grp->fsm));1541 1542 fsm_newstate(fi, CTC_STATE_RXIDLE);1543 /* XID processing complete */1544 1545 switch (fsm_getstate(grp->fsm)) {1546 case MPCG_STATE_FLOWC:1547 case MPCG_STATE_READY:1548 if (ctcm_checkalloc_buffer(ch))1549 goto done;1550 ch->trans_skb->data = ch->trans_skb_data;1551 skb_reset_tail_pointer(ch->trans_skb);1552 ch->trans_skb->len = 0;1553 ch->ccw[1].count = ch->max_bufsize;1554 CTCM_CCW_DUMP((char *)&ch->ccw[0], sizeof(struct ccw1) * 3);1555 if (event == CTC_EVENT_START)1556 /* see remark about conditional locking */1557 spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);1558 rc = ccw_device_start(ch->cdev, &ch->ccw[0], 0, 0xff, 0);1559 if (event == CTC_EVENT_START)1560 spin_unlock_irqrestore(1561 get_ccwdev_lock(ch->cdev), saveflags);1562 if (rc != 0) {1563 fsm_newstate(fi, CTC_STATE_RXINIT);1564 ctcm_ccw_check_rc(ch, rc, "initial RX");1565 goto done;1566 }1567 break;1568 default:1569 break;1570 }1571 1572 fsm_event(priv->fsm, DEV_EVENT_RXUP, dev);1573done:1574 return;1575}1576 1577/*1578 * ctcmpc channel FSM action1579 * called from several points in ctcmpc_ch_fsm1580 * ctcmpc only1581 */1582static void ctcmpc_chx_attn(fsm_instance *fsm, int event, void *arg)1583{1584 struct channel *ch = arg;1585 struct net_device *dev = ch->netdev;1586 struct ctcm_priv *priv = dev->ml_priv;1587 struct mpc_group *grp = priv->mpcg;1588 1589 CTCM_PR_DEBUG("%s(%s): %s(ch=0x%p), cp=%i, ChStat:%s, GrpStat:%s\n",1590 __func__, dev->name, ch->id, ch, smp_processor_id(),1591 fsm_getstate_str(ch->fsm), fsm_getstate_str(grp->fsm));1592 1593 switch (fsm_getstate(grp->fsm)) {1594 case MPCG_STATE_XID2INITW:1595 /* ok..start yside xid exchanges */1596 if (!ch->in_mpcgroup)1597 break;1598 if (fsm_getstate(ch->fsm) == CH_XID0_PENDING) {1599 fsm_deltimer(&grp->timer);1600 fsm_addtimer(&grp->timer,1601 MPC_XID_TIMEOUT_VALUE,1602 MPCG_EVENT_TIMER, dev);1603 fsm_event(grp->fsm, MPCG_EVENT_XID0DO, ch);1604 1605 } else if (fsm_getstate(ch->fsm) < CH_XID7_PENDING1)1606 /* attn rcvd before xid0 processed via bh */1607 fsm_newstate(ch->fsm, CH_XID7_PENDING1);1608 break;1609 case MPCG_STATE_XID2INITX:1610 case MPCG_STATE_XID0IOWAIT:1611 case MPCG_STATE_XID0IOWAIX:1612 /* attn rcvd before xid0 processed on ch1613 but mid-xid0 processing for group */1614 if (fsm_getstate(ch->fsm) < CH_XID7_PENDING1)1615 fsm_newstate(ch->fsm, CH_XID7_PENDING1);1616 break;1617 case MPCG_STATE_XID7INITW:1618 case MPCG_STATE_XID7INITX:1619 case MPCG_STATE_XID7INITI:1620 case MPCG_STATE_XID7INITZ:1621 switch (fsm_getstate(ch->fsm)) {1622 case CH_XID7_PENDING:1623 fsm_newstate(ch->fsm, CH_XID7_PENDING1);1624 break;1625 case CH_XID7_PENDING2:1626 fsm_newstate(ch->fsm, CH_XID7_PENDING3);1627 break;1628 }1629 fsm_event(grp->fsm, MPCG_EVENT_XID7DONE, dev);1630 break;1631 }1632 1633 return;1634}1635 1636/*1637 * ctcmpc channel FSM action1638 * called from one point in ctcmpc_ch_fsm1639 * ctcmpc only1640 */1641static void ctcmpc_chx_attnbusy(fsm_instance *fsm, int event, void *arg)1642{1643 struct channel *ch = arg;1644 struct net_device *dev = ch->netdev;1645 struct ctcm_priv *priv = dev->ml_priv;1646 struct mpc_group *grp = priv->mpcg;1647 1648 CTCM_PR_DEBUG("%s(%s): %s\n ChState:%s GrpState:%s\n",1649 __func__, dev->name, ch->id,1650 fsm_getstate_str(ch->fsm), fsm_getstate_str(grp->fsm));1651 1652 fsm_deltimer(&ch->timer);1653 1654 switch (fsm_getstate(grp->fsm)) {1655 case MPCG_STATE_XID0IOWAIT:1656 /* vtam wants to be primary.start yside xid exchanges*/1657 /* only receive one attn-busy at a time so must not */1658 /* change state each time */1659 grp->changed_side = 1;1660 fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW);1661 break;1662 case MPCG_STATE_XID2INITW:1663 if (grp->changed_side == 1) {1664 grp->changed_side = 2;1665 break;1666 }1667 /* process began via call to establish_conn */1668 /* so must report failure instead of reverting */1669 /* back to ready-for-xid passive state */1670 if (grp->estconnfunc)1671 goto done;1672 /* this attnbusy is NOT the result of xside xid */1673 /* collisions so yside must have been triggered */1674 /* by an ATTN that was not intended to start XID */1675 /* processing. Revert back to ready-for-xid and */1676 /* wait for ATTN interrupt to signal xid start */1677 if (fsm_getstate(ch->fsm) == CH_XID0_INPROGRESS) {1678 fsm_newstate(ch->fsm, CH_XID0_PENDING) ;1679 fsm_deltimer(&grp->timer);1680 goto done;1681 }1682 fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);1683 goto done;1684 case MPCG_STATE_XID2INITX:1685 /* XID2 was received before ATTN Busy for second1686 channel.Send yside xid for second channel.1687 */1688 if (grp->changed_side == 1) {1689 grp->changed_side = 2;1690 break;1691 }1692 fallthrough;1693 case MPCG_STATE_XID0IOWAIX:1694 case MPCG_STATE_XID7INITW:1695 case MPCG_STATE_XID7INITX:1696 case MPCG_STATE_XID7INITI:1697 case MPCG_STATE_XID7INITZ:1698 default:1699 /* multiple attn-busy indicates too out-of-sync */1700 /* and they are certainly not being received as part */1701 /* of valid mpc group negotiations.. */1702 fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);1703 goto done;1704 }1705 1706 if (grp->changed_side == 1) {1707 fsm_deltimer(&grp->timer);1708 fsm_addtimer(&grp->timer, MPC_XID_TIMEOUT_VALUE,1709 MPCG_EVENT_TIMER, dev);1710 }1711 if (ch->in_mpcgroup)1712 fsm_event(grp->fsm, MPCG_EVENT_XID0DO, ch);1713 else1714 CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,1715 "%s(%s): channel %s not added to group",1716 CTCM_FUNTAIL, dev->name, ch->id);1717 1718done:1719 return;1720}1721 1722/*1723 * ctcmpc channel FSM action1724 * called from several points in ctcmpc_ch_fsm1725 * ctcmpc only1726 */1727static void ctcmpc_chx_resend(fsm_instance *fsm, int event, void *arg)1728{1729 struct channel *ch = arg;1730 struct net_device *dev = ch->netdev;1731 struct ctcm_priv *priv = dev->ml_priv;1732 struct mpc_group *grp = priv->mpcg;1733 1734 fsm_event(grp->fsm, MPCG_EVENT_XID0DO, ch);1735 return;1736}1737 1738/*1739 * ctcmpc channel FSM action1740 * called from several points in ctcmpc_ch_fsm1741 * ctcmpc only1742 */1743static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg)1744{1745 struct channel *ach = arg;1746 struct net_device *dev = ach->netdev;1747 struct ctcm_priv *priv = dev->ml_priv;1748 struct mpc_group *grp = priv->mpcg;1749 struct channel *wch = priv->channel[CTCM_WRITE];1750 struct channel *rch = priv->channel[CTCM_READ];1751 struct sk_buff *skb;1752 struct th_sweep *header;1753 int rc = 0;1754 unsigned long saveflags = 0;1755 1756 CTCM_PR_DEBUG("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",1757 __func__, smp_processor_id(), ach, ach->id);1758 1759 if (grp->in_sweep == 0)1760 goto done;1761 1762 CTCM_PR_DBGDATA("%s: 1: ToVTAM_th_seq= %08x\n" ,1763 __func__, wch->th_seq_num);1764 CTCM_PR_DBGDATA("%s: 1: FromVTAM_th_seq= %08x\n" ,1765 __func__, rch->th_seq_num);1766 1767 if (fsm_getstate(wch->fsm) != CTC_STATE_TXIDLE) {1768 /* give the previous IO time to complete */1769 fsm_addtimer(&wch->sweep_timer,1770 200, CTC_EVENT_RSWEEP_TIMER, wch);1771 goto done;1772 }1773 1774 skb = skb_dequeue(&wch->sweep_queue);1775 if (!skb)1776 goto done;1777 1778 if (set_normalized_cda(&wch->ccw[4], skb->data)) {1779 grp->in_sweep = 0;1780 ctcm_clear_busy_do(dev);1781 dev_kfree_skb_any(skb);1782 fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);1783 goto done;1784 } else {1785 refcount_inc(&skb->users);1786 skb_queue_tail(&wch->io_queue, skb);1787 }1788 1789 /* send out the sweep */1790 wch->ccw[4].count = skb->len;1791 1792 header = (struct th_sweep *)skb->data;1793 switch (header->th.th_ch_flag) {1794 case TH_SWEEP_REQ:1795 grp->sweep_req_pend_num--;1796 break;1797 case TH_SWEEP_RESP:1798 grp->sweep_rsp_pend_num--;1799 break;1800 }1801 1802 header->sw.th_last_seq = wch->th_seq_num;1803 1804 CTCM_CCW_DUMP((char *)&wch->ccw[3], sizeof(struct ccw1) * 3);1805 CTCM_PR_DBGDATA("%s: sweep packet\n", __func__);1806 CTCM_D3_DUMP((char *)header, TH_SWEEP_LENGTH);1807 1808 fsm_addtimer(&wch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, wch);1809 fsm_newstate(wch->fsm, CTC_STATE_TX);1810 1811 spin_lock_irqsave(get_ccwdev_lock(wch->cdev), saveflags);1812 wch->prof.send_stamp = jiffies;1813 rc = ccw_device_start(wch->cdev, &wch->ccw[3], 0, 0xff, 0);1814 spin_unlock_irqrestore(get_ccwdev_lock(wch->cdev), saveflags);1815 1816 if ((grp->sweep_req_pend_num == 0) &&1817 (grp->sweep_rsp_pend_num == 0)) {1818 grp->in_sweep = 0;1819 rch->th_seq_num = 0x00;1820 wch->th_seq_num = 0x00;1821 ctcm_clear_busy_do(dev);1822 }1823 1824 CTCM_PR_DBGDATA("%s: To-/From-VTAM_th_seq = %08x/%08x\n" ,1825 __func__, wch->th_seq_num, rch->th_seq_num);1826 1827 if (rc != 0)1828 ctcm_ccw_check_rc(wch, rc, "send sweep");1829 1830done:1831 return;1832}1833 1834 1835/*1836 * The ctcmpc statemachine for a channel.1837 */1838 1839const fsm_node ctcmpc_ch_fsm[] = {1840 { CTC_STATE_STOPPED, CTC_EVENT_STOP, ctcm_action_nop },1841 { CTC_STATE_STOPPED, CTC_EVENT_START, ctcm_chx_start },1842 { CTC_STATE_STOPPED, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1843 { CTC_STATE_STOPPED, CTC_EVENT_FINSTAT, ctcm_action_nop },1844 { CTC_STATE_STOPPED, CTC_EVENT_MC_FAIL, ctcm_action_nop },1845 1846 { CTC_STATE_NOTOP, CTC_EVENT_STOP, ctcm_chx_stop },1847 { CTC_STATE_NOTOP, CTC_EVENT_START, ctcm_action_nop },1848 { CTC_STATE_NOTOP, CTC_EVENT_FINSTAT, ctcm_action_nop },1849 { CTC_STATE_NOTOP, CTC_EVENT_MC_FAIL, ctcm_action_nop },1850 { CTC_STATE_NOTOP, CTC_EVENT_MC_GOOD, ctcm_chx_start },1851 { CTC_STATE_NOTOP, CTC_EVENT_UC_RCRESET, ctcm_chx_stop },1852 { CTC_STATE_NOTOP, CTC_EVENT_UC_RSRESET, ctcm_chx_stop },1853 { CTC_STATE_NOTOP, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1854 1855 { CTC_STATE_STARTWAIT, CTC_EVENT_STOP, ctcm_chx_haltio },1856 { CTC_STATE_STARTWAIT, CTC_EVENT_START, ctcm_action_nop },1857 { CTC_STATE_STARTWAIT, CTC_EVENT_FINSTAT, ctcm_chx_setmode },1858 { CTC_STATE_STARTWAIT, CTC_EVENT_TIMER, ctcm_chx_setuperr },1859 { CTC_STATE_STARTWAIT, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1860 { CTC_STATE_STARTWAIT, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1861 1862 { CTC_STATE_STARTRETRY, CTC_EVENT_STOP, ctcm_chx_haltio },1863 { CTC_STATE_STARTRETRY, CTC_EVENT_TIMER, ctcm_chx_setmode },1864 { CTC_STATE_STARTRETRY, CTC_EVENT_FINSTAT, ctcm_chx_setmode },1865 { CTC_STATE_STARTRETRY, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1866 { CTC_STATE_STARTRETRY, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1867 1868 { CTC_STATE_SETUPWAIT, CTC_EVENT_STOP, ctcm_chx_haltio },1869 { CTC_STATE_SETUPWAIT, CTC_EVENT_START, ctcm_action_nop },1870 { CTC_STATE_SETUPWAIT, CTC_EVENT_FINSTAT, ctcmpc_chx_firstio },1871 { CTC_STATE_SETUPWAIT, CTC_EVENT_UC_RCRESET, ctcm_chx_setuperr },1872 { CTC_STATE_SETUPWAIT, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },1873 { CTC_STATE_SETUPWAIT, CTC_EVENT_TIMER, ctcm_chx_setmode },1874 { CTC_STATE_SETUPWAIT, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1875 { CTC_STATE_SETUPWAIT, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1876 1877 { CTC_STATE_RXINIT, CTC_EVENT_STOP, ctcm_chx_haltio },1878 { CTC_STATE_RXINIT, CTC_EVENT_START, ctcm_action_nop },1879 { CTC_STATE_RXINIT, CTC_EVENT_FINSTAT, ctcmpc_chx_rxidle },1880 { CTC_STATE_RXINIT, CTC_EVENT_UC_RCRESET, ctcm_chx_rxiniterr },1881 { CTC_STATE_RXINIT, CTC_EVENT_UC_RSRESET, ctcm_chx_rxiniterr },1882 { CTC_STATE_RXINIT, CTC_EVENT_TIMER, ctcm_chx_rxiniterr },1883 { CTC_STATE_RXINIT, CTC_EVENT_ATTNBUSY, ctcm_chx_rxinitfail },1884 { CTC_STATE_RXINIT, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1885 { CTC_STATE_RXINIT, CTC_EVENT_UC_ZERO, ctcmpc_chx_firstio },1886 { CTC_STATE_RXINIT, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1887 1888 { CH_XID0_PENDING, CTC_EVENT_FINSTAT, ctcm_action_nop },1889 { CH_XID0_PENDING, CTC_EVENT_ATTN, ctcmpc_chx_attn },1890 { CH_XID0_PENDING, CTC_EVENT_STOP, ctcm_chx_haltio },1891 { CH_XID0_PENDING, CTC_EVENT_START, ctcm_action_nop },1892 { CH_XID0_PENDING, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1893 { CH_XID0_PENDING, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1894 { CH_XID0_PENDING, CTC_EVENT_UC_RCRESET, ctcm_chx_setuperr },1895 { CH_XID0_PENDING, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },1896 { CH_XID0_PENDING, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },1897 { CH_XID0_PENDING, CTC_EVENT_ATTNBUSY, ctcm_chx_iofatal },1898 1899 { CH_XID0_INPROGRESS, CTC_EVENT_FINSTAT, ctcmpc_chx_rx },1900 { CH_XID0_INPROGRESS, CTC_EVENT_ATTN, ctcmpc_chx_attn },1901 { CH_XID0_INPROGRESS, CTC_EVENT_STOP, ctcm_chx_haltio },1902 { CH_XID0_INPROGRESS, CTC_EVENT_START, ctcm_action_nop },1903 { CH_XID0_INPROGRESS, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1904 { CH_XID0_INPROGRESS, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1905 { CH_XID0_INPROGRESS, CTC_EVENT_UC_ZERO, ctcmpc_chx_rx },1906 { CH_XID0_INPROGRESS, CTC_EVENT_UC_RCRESET, ctcm_chx_setuperr },1907 { CH_XID0_INPROGRESS, CTC_EVENT_ATTNBUSY, ctcmpc_chx_attnbusy },1908 { CH_XID0_INPROGRESS, CTC_EVENT_TIMER, ctcmpc_chx_resend },1909 { CH_XID0_INPROGRESS, CTC_EVENT_IO_EBUSY, ctcm_chx_fail },1910 1911 { CH_XID7_PENDING, CTC_EVENT_FINSTAT, ctcmpc_chx_rx },1912 { CH_XID7_PENDING, CTC_EVENT_ATTN, ctcmpc_chx_attn },1913 { CH_XID7_PENDING, CTC_EVENT_STOP, ctcm_chx_haltio },1914 { CH_XID7_PENDING, CTC_EVENT_START, ctcm_action_nop },1915 { CH_XID7_PENDING, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1916 { CH_XID7_PENDING, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1917 { CH_XID7_PENDING, CTC_EVENT_UC_ZERO, ctcmpc_chx_rx },1918 { CH_XID7_PENDING, CTC_EVENT_UC_RCRESET, ctcm_chx_setuperr },1919 { CH_XID7_PENDING, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },1920 { CH_XID7_PENDING, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },1921 { CH_XID7_PENDING, CTC_EVENT_ATTNBUSY, ctcm_chx_iofatal },1922 { CH_XID7_PENDING, CTC_EVENT_TIMER, ctcmpc_chx_resend },1923 { CH_XID7_PENDING, CTC_EVENT_IO_EBUSY, ctcm_chx_fail },1924 1925 { CH_XID7_PENDING1, CTC_EVENT_FINSTAT, ctcmpc_chx_rx },1926 { CH_XID7_PENDING1, CTC_EVENT_ATTN, ctcmpc_chx_attn },1927 { CH_XID7_PENDING1, CTC_EVENT_STOP, ctcm_chx_haltio },1928 { CH_XID7_PENDING1, CTC_EVENT_START, ctcm_action_nop },1929 { CH_XID7_PENDING1, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1930 { CH_XID7_PENDING1, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1931 { CH_XID7_PENDING1, CTC_EVENT_UC_ZERO, ctcmpc_chx_rx },1932 { CH_XID7_PENDING1, CTC_EVENT_UC_RCRESET, ctcm_chx_setuperr },1933 { CH_XID7_PENDING1, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },1934 { CH_XID7_PENDING1, CTC_EVENT_ATTNBUSY, ctcm_chx_iofatal },1935 { CH_XID7_PENDING1, CTC_EVENT_TIMER, ctcmpc_chx_resend },1936 { CH_XID7_PENDING1, CTC_EVENT_IO_EBUSY, ctcm_chx_fail },1937 1938 { CH_XID7_PENDING2, CTC_EVENT_FINSTAT, ctcmpc_chx_rx },1939 { CH_XID7_PENDING2, CTC_EVENT_ATTN, ctcmpc_chx_attn },1940 { CH_XID7_PENDING2, CTC_EVENT_STOP, ctcm_chx_haltio },1941 { CH_XID7_PENDING2, CTC_EVENT_START, ctcm_action_nop },1942 { CH_XID7_PENDING2, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1943 { CH_XID7_PENDING2, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1944 { CH_XID7_PENDING2, CTC_EVENT_UC_ZERO, ctcmpc_chx_rx },1945 { CH_XID7_PENDING2, CTC_EVENT_UC_RCRESET, ctcm_chx_setuperr },1946 { CH_XID7_PENDING2, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },1947 { CH_XID7_PENDING2, CTC_EVENT_ATTNBUSY, ctcm_chx_iofatal },1948 { CH_XID7_PENDING2, CTC_EVENT_TIMER, ctcmpc_chx_resend },1949 { CH_XID7_PENDING2, CTC_EVENT_IO_EBUSY, ctcm_chx_fail },1950 1951 { CH_XID7_PENDING3, CTC_EVENT_FINSTAT, ctcmpc_chx_rx },1952 { CH_XID7_PENDING3, CTC_EVENT_ATTN, ctcmpc_chx_attn },1953 { CH_XID7_PENDING3, CTC_EVENT_STOP, ctcm_chx_haltio },1954 { CH_XID7_PENDING3, CTC_EVENT_START, ctcm_action_nop },1955 { CH_XID7_PENDING3, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1956 { CH_XID7_PENDING3, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1957 { CH_XID7_PENDING3, CTC_EVENT_UC_ZERO, ctcmpc_chx_rx },1958 { CH_XID7_PENDING3, CTC_EVENT_UC_RCRESET, ctcm_chx_setuperr },1959 { CH_XID7_PENDING3, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },1960 { CH_XID7_PENDING3, CTC_EVENT_ATTNBUSY, ctcm_chx_iofatal },1961 { CH_XID7_PENDING3, CTC_EVENT_TIMER, ctcmpc_chx_resend },1962 { CH_XID7_PENDING3, CTC_EVENT_IO_EBUSY, ctcm_chx_fail },1963 1964 { CH_XID7_PENDING4, CTC_EVENT_FINSTAT, ctcmpc_chx_rx },1965 { CH_XID7_PENDING4, CTC_EVENT_ATTN, ctcmpc_chx_attn },1966 { CH_XID7_PENDING4, CTC_EVENT_STOP, ctcm_chx_haltio },1967 { CH_XID7_PENDING4, CTC_EVENT_START, ctcm_action_nop },1968 { CH_XID7_PENDING4, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1969 { CH_XID7_PENDING4, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1970 { CH_XID7_PENDING4, CTC_EVENT_UC_ZERO, ctcmpc_chx_rx },1971 { CH_XID7_PENDING4, CTC_EVENT_UC_RCRESET, ctcm_chx_setuperr },1972 { CH_XID7_PENDING4, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },1973 { CH_XID7_PENDING4, CTC_EVENT_ATTNBUSY, ctcm_chx_iofatal },1974 { CH_XID7_PENDING4, CTC_EVENT_TIMER, ctcmpc_chx_resend },1975 { CH_XID7_PENDING4, CTC_EVENT_IO_EBUSY, ctcm_chx_fail },1976 1977 { CTC_STATE_RXIDLE, CTC_EVENT_STOP, ctcm_chx_haltio },1978 { CTC_STATE_RXIDLE, CTC_EVENT_START, ctcm_action_nop },1979 { CTC_STATE_RXIDLE, CTC_EVENT_FINSTAT, ctcmpc_chx_rx },1980 { CTC_STATE_RXIDLE, CTC_EVENT_UC_RCRESET, ctcm_chx_rxdisc },1981 { CTC_STATE_RXIDLE, CTC_EVENT_UC_RSRESET, ctcm_chx_fail },1982 { CTC_STATE_RXIDLE, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1983 { CTC_STATE_RXIDLE, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1984 { CTC_STATE_RXIDLE, CTC_EVENT_UC_ZERO, ctcmpc_chx_rx },1985 1986 { CTC_STATE_TXINIT, CTC_EVENT_STOP, ctcm_chx_haltio },1987 { CTC_STATE_TXINIT, CTC_EVENT_START, ctcm_action_nop },1988 { CTC_STATE_TXINIT, CTC_EVENT_FINSTAT, ctcm_chx_txidle },1989 { CTC_STATE_TXINIT, CTC_EVENT_UC_RCRESET, ctcm_chx_txiniterr },1990 { CTC_STATE_TXINIT, CTC_EVENT_UC_RSRESET, ctcm_chx_txiniterr },1991 { CTC_STATE_TXINIT, CTC_EVENT_TIMER, ctcm_chx_txiniterr },1992 { CTC_STATE_TXINIT, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },1993 { CTC_STATE_TXINIT, CTC_EVENT_MC_FAIL, ctcm_chx_fail },1994 { CTC_STATE_TXINIT, CTC_EVENT_RSWEEP_TIMER, ctcmpc_chx_send_sweep },1995 1996 { CTC_STATE_TXIDLE, CTC_EVENT_STOP, ctcm_chx_haltio },1997 { CTC_STATE_TXIDLE, CTC_EVENT_START, ctcm_action_nop },1998 { CTC_STATE_TXIDLE, CTC_EVENT_FINSTAT, ctcmpc_chx_firstio },1999 { CTC_STATE_TXIDLE, CTC_EVENT_UC_RCRESET, ctcm_chx_fail },2000 { CTC_STATE_TXIDLE, CTC_EVENT_UC_RSRESET, ctcm_chx_fail },2001 { CTC_STATE_TXIDLE, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },2002 { CTC_STATE_TXIDLE, CTC_EVENT_MC_FAIL, ctcm_chx_fail },2003 { CTC_STATE_TXIDLE, CTC_EVENT_RSWEEP_TIMER, ctcmpc_chx_send_sweep },2004 2005 { CTC_STATE_TERM, CTC_EVENT_STOP, ctcm_action_nop },2006 { CTC_STATE_TERM, CTC_EVENT_START, ctcm_chx_restart },2007 { CTC_STATE_TERM, CTC_EVENT_FINSTAT, ctcm_chx_stopped },2008 { CTC_STATE_TERM, CTC_EVENT_UC_RCRESET, ctcm_action_nop },2009 { CTC_STATE_TERM, CTC_EVENT_UC_RSRESET, ctcm_action_nop },2010 { CTC_STATE_TERM, CTC_EVENT_MC_FAIL, ctcm_chx_fail },2011 { CTC_STATE_TERM, CTC_EVENT_IO_EBUSY, ctcm_chx_fail },2012 { CTC_STATE_TERM, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },2013 2014 { CTC_STATE_DTERM, CTC_EVENT_STOP, ctcm_chx_haltio },2015 { CTC_STATE_DTERM, CTC_EVENT_START, ctcm_chx_restart },2016 { CTC_STATE_DTERM, CTC_EVENT_FINSTAT, ctcm_chx_setmode },2017 { CTC_STATE_DTERM, CTC_EVENT_UC_RCRESET, ctcm_action_nop },2018 { CTC_STATE_DTERM, CTC_EVENT_UC_RSRESET, ctcm_action_nop },2019 { CTC_STATE_DTERM, CTC_EVENT_MC_FAIL, ctcm_chx_fail },2020 { CTC_STATE_DTERM, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },2021 2022 { CTC_STATE_TX, CTC_EVENT_STOP, ctcm_chx_haltio },2023 { CTC_STATE_TX, CTC_EVENT_START, ctcm_action_nop },2024 { CTC_STATE_TX, CTC_EVENT_FINSTAT, ctcmpc_chx_txdone },2025 { CTC_STATE_TX, CTC_EVENT_UC_RCRESET, ctcm_chx_fail },2026 { CTC_STATE_TX, CTC_EVENT_UC_RSRESET, ctcm_chx_fail },2027 { CTC_STATE_TX, CTC_EVENT_TIMER, ctcm_chx_txretry },2028 { CTC_STATE_TX, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },2029 { CTC_STATE_TX, CTC_EVENT_MC_FAIL, ctcm_chx_fail },2030 { CTC_STATE_TX, CTC_EVENT_RSWEEP_TIMER, ctcmpc_chx_send_sweep },2031 { CTC_STATE_TX, CTC_EVENT_IO_EBUSY, ctcm_chx_fail },2032 2033 { CTC_STATE_RXERR, CTC_EVENT_STOP, ctcm_chx_haltio },2034 { CTC_STATE_TXERR, CTC_EVENT_STOP, ctcm_chx_haltio },2035 { CTC_STATE_TXERR, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },2036 { CTC_STATE_TXERR, CTC_EVENT_MC_FAIL, ctcm_chx_fail },2037 { CTC_STATE_RXERR, CTC_EVENT_MC_FAIL, ctcm_chx_fail },2038};2039 2040int mpc_ch_fsm_len = ARRAY_SIZE(ctcmpc_ch_fsm);2041 2042/*2043 * Actions for interface - statemachine.2044 */2045 2046/*2047 * Startup channels by sending CTC_EVENT_START to each channel.2048 *2049 * fi An instance of an interface statemachine.2050 * event The event, just happened.2051 * arg Generic pointer, casted from struct net_device * upon call.2052 */2053static void dev_action_start(fsm_instance *fi, int event, void *arg)2054{2055 struct net_device *dev = arg;2056 struct ctcm_priv *priv = dev->ml_priv;2057 int direction;2058 2059 CTCMY_DBF_DEV_NAME(SETUP, dev, "");2060 2061 fsm_deltimer(&priv->restart_timer);2062 fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);2063 if (IS_MPC(priv))2064 priv->mpcg->channels_terminating = 0;2065 for (direction = CTCM_READ; direction <= CTCM_WRITE; direction++) {2066 struct channel *ch = priv->channel[direction];2067 fsm_event(ch->fsm, CTC_EVENT_START, ch);2068 }2069}2070 2071/*2072 * Shutdown channels by sending CTC_EVENT_STOP to each channel.2073 *2074 * fi An instance of an interface statemachine.2075 * event The event, just happened.2076 * arg Generic pointer, casted from struct net_device * upon call.2077 */2078static void dev_action_stop(fsm_instance *fi, int event, void *arg)2079{2080 int direction;2081 struct net_device *dev = arg;2082 struct ctcm_priv *priv = dev->ml_priv;2083 2084 CTCMY_DBF_DEV_NAME(SETUP, dev, "");2085 2086 fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);2087 for (direction = CTCM_READ; direction <= CTCM_WRITE; direction++) {2088 struct channel *ch = priv->channel[direction];2089 fsm_event(ch->fsm, CTC_EVENT_STOP, ch);2090 ch->th_seq_num = 0x00;2091 CTCM_PR_DEBUG("%s: CH_th_seq= %08x\n",2092 __func__, ch->th_seq_num);2093 }2094 if (IS_MPC(priv))2095 fsm_newstate(priv->mpcg->fsm, MPCG_STATE_RESET);2096}2097 2098static void dev_action_restart(fsm_instance *fi, int event, void *arg)2099{2100 int restart_timer;2101 struct net_device *dev = arg;2102 struct ctcm_priv *priv = dev->ml_priv;2103 2104 CTCMY_DBF_DEV_NAME(TRACE, dev, "");2105 2106 if (IS_MPC(priv)) {2107 restart_timer = CTCM_TIME_1_SEC;2108 } else {2109 restart_timer = CTCM_TIME_5_SEC;2110 }2111 dev_info(&dev->dev, "Restarting device\n");2112 2113 dev_action_stop(fi, event, arg);2114 fsm_event(priv->fsm, DEV_EVENT_STOP, dev);2115 if (IS_MPC(priv))2116 fsm_newstate(priv->mpcg->fsm, MPCG_STATE_RESET);2117 2118 /* going back into start sequence too quickly can */2119 /* result in the other side becoming unreachable due */2120 /* to sense reported when IO is aborted */2121 fsm_addtimer(&priv->restart_timer, restart_timer,2122 DEV_EVENT_START, dev);2123}2124 2125/*2126 * Called from channel statemachine2127 * when a channel is up and running.2128 *2129 * fi An instance of an interface statemachine.2130 * event The event, just happened.2131 * arg Generic pointer, casted from struct net_device * upon call.2132 */2133static void dev_action_chup(fsm_instance *fi, int event, void *arg)2134{2135 struct net_device *dev = arg;2136 struct ctcm_priv *priv = dev->ml_priv;2137 int dev_stat = fsm_getstate(fi);2138 2139 CTCM_DBF_TEXT_(SETUP, CTC_DBF_NOTICE,2140 "%s(%s): priv = %p [%d,%d]\n ", CTCM_FUNTAIL,2141 dev->name, dev->ml_priv, dev_stat, event);2142 2143 switch (fsm_getstate(fi)) {2144 case DEV_STATE_STARTWAIT_RXTX:2145 if (event == DEV_EVENT_RXUP)2146 fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);2147 else2148 fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);2149 break;2150 case DEV_STATE_STARTWAIT_RX:2151 if (event == DEV_EVENT_RXUP) {2152 fsm_newstate(fi, DEV_STATE_RUNNING);2153 dev_info(&dev->dev,2154 "Connected with remote side\n");2155 ctcm_clear_busy(dev);2156 }2157 break;2158 case DEV_STATE_STARTWAIT_TX:2159 if (event == DEV_EVENT_TXUP) {2160 fsm_newstate(fi, DEV_STATE_RUNNING);2161 dev_info(&dev->dev,2162 "Connected with remote side\n");2163 ctcm_clear_busy(dev);2164 }2165 break;2166 case DEV_STATE_STOPWAIT_TX:2167 if (event == DEV_EVENT_RXUP)2168 fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);2169 break;2170 case DEV_STATE_STOPWAIT_RX:2171 if (event == DEV_EVENT_TXUP)2172 fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);2173 break;2174 }2175 2176 if (IS_MPC(priv)) {2177 if (event == DEV_EVENT_RXUP)2178 mpc_channel_action(priv->channel[CTCM_READ],2179 CTCM_READ, MPC_CHANNEL_ADD);2180 else2181 mpc_channel_action(priv->channel[CTCM_WRITE],2182 CTCM_WRITE, MPC_CHANNEL_ADD);2183 }2184}2185 2186/*2187 * Called from device statemachine2188 * when a channel has been shutdown.2189 *2190 * fi An instance of an interface statemachine.2191 * event The event, just happened.2192 * arg Generic pointer, casted from struct net_device * upon call.2193 */2194static void dev_action_chdown(fsm_instance *fi, int event, void *arg)2195{2196 2197 struct net_device *dev = arg;2198 struct ctcm_priv *priv = dev->ml_priv;2199 2200 CTCMY_DBF_DEV_NAME(SETUP, dev, "");2201 2202 switch (fsm_getstate(fi)) {2203 case DEV_STATE_RUNNING:2204 if (event == DEV_EVENT_TXDOWN)2205 fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);2206 else2207 fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);2208 break;2209 case DEV_STATE_STARTWAIT_RX:2210 if (event == DEV_EVENT_TXDOWN)2211 fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);2212 break;2213 case DEV_STATE_STARTWAIT_TX:2214 if (event == DEV_EVENT_RXDOWN)2215 fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);2216 break;2217 case DEV_STATE_STOPWAIT_RXTX:2218 if (event == DEV_EVENT_TXDOWN)2219 fsm_newstate(fi, DEV_STATE_STOPWAIT_RX);2220 else2221 fsm_newstate(fi, DEV_STATE_STOPWAIT_TX);2222 break;2223 case DEV_STATE_STOPWAIT_RX:2224 if (event == DEV_EVENT_RXDOWN)2225 fsm_newstate(fi, DEV_STATE_STOPPED);2226 break;2227 case DEV_STATE_STOPWAIT_TX:2228 if (event == DEV_EVENT_TXDOWN)2229 fsm_newstate(fi, DEV_STATE_STOPPED);2230 break;2231 }2232 if (IS_MPC(priv)) {2233 if (event == DEV_EVENT_RXDOWN)2234 mpc_channel_action(priv->channel[CTCM_READ],2235 CTCM_READ, MPC_CHANNEL_REMOVE);2236 else2237 mpc_channel_action(priv->channel[CTCM_WRITE],2238 CTCM_WRITE, MPC_CHANNEL_REMOVE);2239 }2240}2241 2242const fsm_node dev_fsm[] = {2243 { DEV_STATE_STOPPED, DEV_EVENT_START, dev_action_start },2244 { DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_START, dev_action_start },2245 { DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_RXDOWN, dev_action_chdown },2246 { DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_TXDOWN, dev_action_chdown },2247 { DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_RESTART, dev_action_restart },2248 { DEV_STATE_STOPWAIT_RX, DEV_EVENT_START, dev_action_start },2249 { DEV_STATE_STOPWAIT_RX, DEV_EVENT_RXUP, dev_action_chup },2250 { DEV_STATE_STOPWAIT_RX, DEV_EVENT_TXUP, dev_action_chup },2251 { DEV_STATE_STOPWAIT_RX, DEV_EVENT_RXDOWN, dev_action_chdown },2252 { DEV_STATE_STOPWAIT_RX, DEV_EVENT_RESTART, dev_action_restart },2253 { DEV_STATE_STOPWAIT_TX, DEV_EVENT_START, dev_action_start },2254 { DEV_STATE_STOPWAIT_TX, DEV_EVENT_RXUP, dev_action_chup },2255 { DEV_STATE_STOPWAIT_TX, DEV_EVENT_TXUP, dev_action_chup },2256 { DEV_STATE_STOPWAIT_TX, DEV_EVENT_TXDOWN, dev_action_chdown },2257 { DEV_STATE_STOPWAIT_TX, DEV_EVENT_RESTART, dev_action_restart },2258 { DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_STOP, dev_action_stop },2259 { DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXUP, dev_action_chup },2260 { DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXUP, dev_action_chup },2261 { DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXDOWN, dev_action_chdown },2262 { DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXDOWN, dev_action_chdown },2263 { DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RESTART, dev_action_restart },2264 { DEV_STATE_STARTWAIT_TX, DEV_EVENT_STOP, dev_action_stop },2265 { DEV_STATE_STARTWAIT_TX, DEV_EVENT_RXUP, dev_action_chup },2266 { DEV_STATE_STARTWAIT_TX, DEV_EVENT_TXUP, dev_action_chup },2267 { DEV_STATE_STARTWAIT_TX, DEV_EVENT_RXDOWN, dev_action_chdown },2268 { DEV_STATE_STARTWAIT_TX, DEV_EVENT_RESTART, dev_action_restart },2269 { DEV_STATE_STARTWAIT_RX, DEV_EVENT_STOP, dev_action_stop },2270 { DEV_STATE_STARTWAIT_RX, DEV_EVENT_RXUP, dev_action_chup },2271 { DEV_STATE_STARTWAIT_RX, DEV_EVENT_TXUP, dev_action_chup },2272 { DEV_STATE_STARTWAIT_RX, DEV_EVENT_TXDOWN, dev_action_chdown },2273 { DEV_STATE_STARTWAIT_RX, DEV_EVENT_RESTART, dev_action_restart },2274 { DEV_STATE_RUNNING, DEV_EVENT_STOP, dev_action_stop },2275 { DEV_STATE_RUNNING, DEV_EVENT_RXDOWN, dev_action_chdown },2276 { DEV_STATE_RUNNING, DEV_EVENT_TXDOWN, dev_action_chdown },2277 { DEV_STATE_RUNNING, DEV_EVENT_TXUP, ctcm_action_nop },2278 { DEV_STATE_RUNNING, DEV_EVENT_RXUP, ctcm_action_nop },2279 { DEV_STATE_RUNNING, DEV_EVENT_RESTART, dev_action_restart },2280};2281 2282int dev_fsm_len = ARRAY_SIZE(dev_fsm);2283 2284/* --- This is the END my friend --- */2285 2286