^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright IBM Corp. 2001, 2009
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Author(s):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Original CTC driver(s):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Fritz Elfert (felfert@millenux.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Dieter Wellerdiek (wel@de.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Martin Schwidefsky (schwidefsky@de.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Denis Joseph Barrow (barrow_dj@yahoo.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Jochen Roehrig (roehrig@de.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Cornelia Huck <cornelia.huck@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * MPC additions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Belinda Thompson (belindat@us.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Andy Richter (richtera@us.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Revived by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Peter Tiedemann (ptiedem@de.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #undef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #undef DEBUGDATA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #undef DEBUGCCW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define KMSG_COMPONENT "ctcm"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/ip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/tcp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <net/dst.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <asm/ccwdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <asm/ccwgroup.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <asm/idals.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include "ctcm_fsms.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include "ctcm_main.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* Some common global variables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * The root device for ctcm group devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static struct device *ctcm_root_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * Linked list of all detected channels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct channel *channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * Unpack a just received skb and hand it over to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * upper layers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * ch The channel where this skb has been received.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * pskb The received skb.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct net_device *dev = ch->netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct ctcm_priv *priv = dev->ml_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) __u16 len = *((__u16 *) pskb->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) skb_put(pskb, 2 + LL_HEADER_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) skb_pull(pskb, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) pskb->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) pskb->ip_summed = CHECKSUM_UNNECESSARY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) while (len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) int skblen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct ll_header *header = (struct ll_header *)pskb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) skb_pull(pskb, LL_HEADER_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if ((ch->protocol == CTCM_PROTO_S390) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) (header->type != ETH_P_IP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (!(ch->logflags & LOG_FLAG_ILLEGALPKT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) ch->logflags |= LOG_FLAG_ILLEGALPKT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * Check packet type only if we stick strictly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * to S/390's protocol of OS390. This only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * supports IP. Otherwise allow any packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) "%s(%s): Illegal packet type 0x%04x"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) " - dropping",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) CTCM_FUNTAIL, dev->name, header->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) priv->stats.rx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) priv->stats.rx_frame_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) pskb->protocol = cpu_to_be16(header->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if ((header->length <= LL_HEADER_LENGTH) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) (len <= LL_HEADER_LENGTH)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (!(ch->logflags & LOG_FLAG_ILLEGALSIZE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) "%s(%s): Illegal packet size %d(%d,%d)"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) "- dropping",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) CTCM_FUNTAIL, dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) header->length, dev->mtu, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) ch->logflags |= LOG_FLAG_ILLEGALSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) priv->stats.rx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) priv->stats.rx_length_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) header->length -= LL_HEADER_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) len -= LL_HEADER_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if ((header->length > skb_tailroom(pskb)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) (header->length > len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (!(ch->logflags & LOG_FLAG_OVERRUN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) "%s(%s): Packet size %d (overrun)"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) " - dropping", CTCM_FUNTAIL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) dev->name, header->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) ch->logflags |= LOG_FLAG_OVERRUN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) priv->stats.rx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) priv->stats.rx_length_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) skb_put(pskb, header->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) skb_reset_mac_header(pskb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) len -= header->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) skb = dev_alloc_skb(pskb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (!skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (!(ch->logflags & LOG_FLAG_NOMEM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) "%s(%s): MEMORY allocation error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) CTCM_FUNTAIL, dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) ch->logflags |= LOG_FLAG_NOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) priv->stats.rx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) skb_copy_from_linear_data(pskb, skb_put(skb, pskb->len),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) pskb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) skb_reset_mac_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) skb->dev = pskb->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) skb->protocol = pskb->protocol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) pskb->ip_summed = CHECKSUM_UNNECESSARY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) skblen = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * reset logflags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ch->logflags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) priv->stats.rx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) priv->stats.rx_bytes += skblen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) netif_rx_ni(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) skb_pull(pskb, header->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (skb_tailroom(pskb) < LL_HEADER_LENGTH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) CTCM_DBF_DEV_NAME(TRACE, dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) "Overrun in ctcm_unpack_skb");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ch->logflags |= LOG_FLAG_OVERRUN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) skb_put(pskb, LL_HEADER_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * Release a specific channel in the channel list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * ch Pointer to channel struct to be released.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static void channel_free(struct channel *ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s(%s)", CTCM_FUNTAIL, ch->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ch->flags &= ~CHANNEL_FLAGS_INUSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) fsm_newstate(ch->fsm, CTC_STATE_IDLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * Remove a specific channel in the channel list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * ch Pointer to channel struct to be released.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static void channel_remove(struct channel *ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct channel **c = &channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) char chid[CTCM_ID_SIZE+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) int ok = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (ch == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) strncpy(chid, ch->id, CTCM_ID_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) channel_free(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) while (*c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (*c == ch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) *c = ch->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) fsm_deltimer(&ch->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (IS_MPC(ch))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) fsm_deltimer(&ch->sweep_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) kfree_fsm(ch->fsm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) clear_normalized_cda(&ch->ccw[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (ch->trans_skb != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) clear_normalized_cda(&ch->ccw[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) dev_kfree_skb_any(ch->trans_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (IS_MPC(ch)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) tasklet_kill(&ch->ch_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) tasklet_kill(&ch->ch_disc_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) kfree(ch->discontact_th);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) kfree(ch->ccw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) kfree(ch->irb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) kfree(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) ok = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) c = &((*c)->next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s(%s) %s", CTCM_FUNTAIL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) chid, ok ? "OK" : "failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * Get a specific channel from the channel list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * type Type of channel we are interested in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * id Id of channel we are interested in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * direction Direction we want to use this channel for.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * returns Pointer to a channel or NULL if no matching channel available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static struct channel *channel_get(enum ctcm_channel_types type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) char *id, int direction)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct channel *ch = channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) while (ch && (strncmp(ch->id, id, CTCM_ID_SIZE) || (ch->type != type)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) ch = ch->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (!ch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) "%s(%d, %s, %d) not found in channel list\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) CTCM_FUNTAIL, type, id, direction);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (ch->flags & CHANNEL_FLAGS_INUSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) ch = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) ch->flags |= CHANNEL_FLAGS_INUSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) ch->flags &= ~CHANNEL_FLAGS_RWMASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) ch->flags |= (direction == CTCM_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) ? CHANNEL_FLAGS_WRITE : CHANNEL_FLAGS_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) fsm_newstate(ch->fsm, CTC_STATE_STOPPED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static long ctcm_check_irb_error(struct ccw_device *cdev, struct irb *irb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (!IS_ERR(irb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) CTCM_DBF_TEXT_(ERROR, CTC_DBF_WARN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) "irb error %ld on device %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) PTR_ERR(irb), dev_name(&cdev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) switch (PTR_ERR(irb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) case -EIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) dev_err(&cdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) "An I/O-error occurred on the CTCM device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) case -ETIMEDOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) dev_err(&cdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) "An adapter hardware operation timed out\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) dev_err(&cdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) "An error occurred on the adapter hardware\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return PTR_ERR(irb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * Check sense of a unit check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * ch The channel, the sense code belongs to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * sense The sense code to inspect.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static void ccw_unit_check(struct channel *ch, __u8 sense)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) "%s(%s): %02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) CTCM_FUNTAIL, ch->id, sense);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (sense & SNS0_INTERVENTION_REQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (sense & 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (ch->sense_rc != 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) pr_notice(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) "%s: The communication peer has "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) "disconnected\n", ch->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) ch->sense_rc = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) fsm_event(ch->fsm, CTC_EVENT_UC_RCRESET, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (ch->sense_rc != SNS0_INTERVENTION_REQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) pr_notice(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) "%s: The remote operating system is "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) "not available\n", ch->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) ch->sense_rc = SNS0_INTERVENTION_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) fsm_event(ch->fsm, CTC_EVENT_UC_RSRESET, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) } else if (sense & SNS0_EQUIPMENT_CHECK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (sense & SNS0_BUS_OUT_CHECK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (ch->sense_rc != SNS0_BUS_OUT_CHECK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) "%s(%s): remote HW error %02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) CTCM_FUNTAIL, ch->id, sense);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) ch->sense_rc = SNS0_BUS_OUT_CHECK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) fsm_event(ch->fsm, CTC_EVENT_UC_HWFAIL, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (ch->sense_rc != SNS0_EQUIPMENT_CHECK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) "%s(%s): remote read parity error %02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) CTCM_FUNTAIL, ch->id, sense);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) ch->sense_rc = SNS0_EQUIPMENT_CHECK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) fsm_event(ch->fsm, CTC_EVENT_UC_RXPARITY, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) } else if (sense & SNS0_BUS_OUT_CHECK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (ch->sense_rc != SNS0_BUS_OUT_CHECK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) "%s(%s): BUS OUT error %02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) CTCM_FUNTAIL, ch->id, sense);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) ch->sense_rc = SNS0_BUS_OUT_CHECK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (sense & 0x04) /* data-streaming timeout */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) fsm_event(ch->fsm, CTC_EVENT_UC_TXTIMEOUT, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) else /* Data-transfer parity error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) fsm_event(ch->fsm, CTC_EVENT_UC_TXPARITY, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) } else if (sense & SNS0_CMD_REJECT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (ch->sense_rc != SNS0_CMD_REJECT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) "%s(%s): Command rejected",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) CTCM_FUNTAIL, ch->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) ch->sense_rc = SNS0_CMD_REJECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) } else if (sense == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) "%s(%s): Unit check ZERO",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) CTCM_FUNTAIL, ch->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) fsm_event(ch->fsm, CTC_EVENT_UC_ZERO, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) "%s(%s): Unit check code %02x unknown",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) CTCM_FUNTAIL, ch->id, sense);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) fsm_event(ch->fsm, CTC_EVENT_UC_UNKNOWN, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) int ctcm_ch_alloc_buffer(struct channel *ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) clear_normalized_cda(&ch->ccw[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) ch->trans_skb = __dev_alloc_skb(ch->max_bufsize, GFP_ATOMIC | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (ch->trans_skb == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) "%s(%s): %s trans_skb allocation error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) CTCM_FUNTAIL, ch->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) "RX" : "TX");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) ch->ccw[1].count = ch->max_bufsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) dev_kfree_skb(ch->trans_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) ch->trans_skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) "%s(%s): %s set norm_cda failed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) CTCM_FUNTAIL, ch->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) "RX" : "TX");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) ch->ccw[1].count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) ch->trans_skb_data = ch->trans_skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) ch->flags &= ~CHANNEL_FLAGS_BUFSIZE_CHANGED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * Interface API for upper network layers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * Open an interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * Called from generic network layer when ifconfig up is run.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * dev Pointer to interface struct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * returns 0 on success, -ERRNO on failure. (Never fails.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) int ctcm_open(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) struct ctcm_priv *priv = dev->ml_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) CTCMY_DBF_DEV_NAME(SETUP, dev, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (!IS_MPC(priv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) fsm_event(priv->fsm, DEV_EVENT_START, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) * Close an interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) * Called from generic network layer when ifconfig down is run.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * dev Pointer to interface struct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * returns 0 on success, -ERRNO on failure. (Never fails.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) int ctcm_close(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) struct ctcm_priv *priv = dev->ml_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) CTCMY_DBF_DEV_NAME(SETUP, dev, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (!IS_MPC(priv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) fsm_event(priv->fsm, DEV_EVENT_STOP, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) * Transmit a packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) * This is a helper function for ctcm_tx().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * ch Channel to be used for sending.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * skb Pointer to struct sk_buff of packet to send.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) * The linklevel header has already been set up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) * by ctcm_tx().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) * returns 0 on success, -ERRNO on failure. (Never fails.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) unsigned long saveflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) struct ll_header header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) __u16 block_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) int ccw_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) struct sk_buff *nskb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) unsigned long hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) /* we need to acquire the lock for testing the state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * otherwise we can have an IRQ changing the state to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) * TXIDLE after the test but before acquiring the lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) spin_lock_irqsave(&ch->collect_lock, saveflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (fsm_getstate(ch->fsm) != CTC_STATE_TXIDLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) int l = skb->len + LL_HEADER_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (ch->collect_len + l > ch->max_bufsize - 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) spin_unlock_irqrestore(&ch->collect_lock, saveflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) refcount_inc(&skb->users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) header.length = l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) header.type = be16_to_cpu(skb->protocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) header.unused = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) memcpy(skb_push(skb, LL_HEADER_LENGTH), &header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) LL_HEADER_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) skb_queue_tail(&ch->collect_queue, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) ch->collect_len += l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) spin_unlock_irqrestore(&ch->collect_lock, saveflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) spin_unlock_irqrestore(&ch->collect_lock, saveflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) * Protect skb against beeing free'd by upper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) * layers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) refcount_inc(&skb->users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) ch->prof.txlen += skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) header.length = skb->len + LL_HEADER_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) header.type = be16_to_cpu(skb->protocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) header.unused = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) memcpy(skb_push(skb, LL_HEADER_LENGTH), &header, LL_HEADER_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) block_len = skb->len + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) *((__u16 *)skb_push(skb, 2)) = block_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * IDAL support in CTCM is broken, so we have to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) * care about skb's above 2G ourselves.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) hi = ((unsigned long)skb_tail_pointer(skb) + LL_HEADER_LENGTH) >> 31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (hi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) nskb = alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (!nskb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) refcount_dec(&skb->users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) skb_pull(skb, LL_HEADER_LENGTH + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) ctcm_clear_busy(ch->netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) skb_put_data(nskb, skb->data, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) refcount_inc(&nskb->users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) refcount_dec(&skb->users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) dev_kfree_skb_irq(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) skb = nskb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) ch->ccw[4].count = block_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (set_normalized_cda(&ch->ccw[4], skb->data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * idal allocation failed, try via copying to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) * trans_skb. trans_skb usually has a pre-allocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * idal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (ctcm_checkalloc_buffer(ch)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) * Remove our header. It gets added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) * again on retransmit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) refcount_dec(&skb->users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) skb_pull(skb, LL_HEADER_LENGTH + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) ctcm_clear_busy(ch->netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) skb_reset_tail_pointer(ch->trans_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) ch->trans_skb->len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) ch->ccw[1].count = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) skb_copy_from_linear_data(skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) skb_put(ch->trans_skb, skb->len), skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) refcount_dec(&skb->users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) dev_kfree_skb_irq(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) ccw_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) skb_queue_tail(&ch->io_queue, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) ccw_idx = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (do_debug_ccw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) ctcmpc_dumpit((char *)&ch->ccw[ccw_idx],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) sizeof(struct ccw1) * 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) ch->retry = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) fsm_newstate(ch->fsm, CTC_STATE_TX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) ch->prof.send_stamp = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) rc = ccw_device_start(ch->cdev, &ch->ccw[ccw_idx], 0, 0xff, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (ccw_idx == 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) ch->prof.doios_single++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) fsm_deltimer(&ch->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) ctcm_ccw_check_rc(ch, rc, "single skb TX");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (ccw_idx == 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) skb_dequeue_tail(&ch->io_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) * Remove our header. It gets added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * again on retransmit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) skb_pull(skb, LL_HEADER_LENGTH + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) } else if (ccw_idx == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) struct net_device *dev = ch->netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) struct ctcm_priv *priv = dev->ml_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) priv->stats.tx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) priv->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) ctcm_clear_busy(ch->netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) static void ctcmpc_send_sweep_req(struct channel *rch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) struct net_device *dev = rch->netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) struct ctcm_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) struct mpc_group *grp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) struct th_sweep *header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) struct sk_buff *sweep_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) struct channel *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /* int rc = 0; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) priv = dev->ml_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) grp = priv->mpcg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) ch = priv->channel[CTCM_WRITE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) /* sweep processing is not complete until response and request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /* has completed for all read channels in group */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (grp->in_sweep == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) grp->in_sweep = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) grp->sweep_rsp_pend_num = grp->active_channels[CTCM_READ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) grp->sweep_req_pend_num = grp->active_channels[CTCM_READ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC|GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (sweep_skb == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /* rc = -ENOMEM; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) goto nomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) header = kmalloc(TH_SWEEP_LENGTH, gfp_type());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (!header) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) dev_kfree_skb_any(sweep_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) /* rc = -ENOMEM; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) goto nomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) header->th.th_seg = 0x00 ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) header->th.th_ch_flag = TH_SWEEP_REQ; /* 0x0f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) header->th.th_blk_flag = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) header->th.th_is_xid = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) header->th.th_seq_num = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) header->sw.th_last_seq = ch->th_seq_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) skb_put_data(sweep_skb, header, TH_SWEEP_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) kfree(header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) netif_trans_update(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) skb_queue_tail(&ch->sweep_queue, sweep_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) fsm_addtimer(&ch->sweep_timer, 100, CTC_EVENT_RSWEEP_TIMER, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) nomem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) grp->in_sweep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) ctcm_clear_busy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) * MPC mode version of transmit_skb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) struct pdu *p_header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) struct net_device *dev = ch->netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) struct ctcm_priv *priv = dev->ml_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) struct mpc_group *grp = priv->mpcg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct th_header *header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) struct sk_buff *nskb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) int ccw_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) unsigned long hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) unsigned long saveflags = 0; /* avoids compiler warning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) CTCM_PR_DEBUG("Enter %s: %s, cp=%i ch=0x%p id=%s state=%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) __func__, dev->name, smp_processor_id(), ch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) ch->id, fsm_getstate_str(ch->fsm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if ((fsm_getstate(ch->fsm) != CTC_STATE_TXIDLE) || grp->in_sweep) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) spin_lock_irqsave(&ch->collect_lock, saveflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) refcount_inc(&skb->users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (!p_header) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) spin_unlock_irqrestore(&ch->collect_lock, saveflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) goto nomem_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) p_header->pdu_offset = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) p_header->pdu_proto = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) p_header->pdu_flag = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (be16_to_cpu(skb->protocol) == ETH_P_SNAP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) p_header->pdu_flag |= PDU_FIRST | PDU_CNTL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) p_header->pdu_flag |= PDU_FIRST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) p_header->pdu_seq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) memcpy(skb_push(skb, PDU_HEADER_LENGTH), p_header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) PDU_HEADER_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) CTCM_PR_DEBUG("%s(%s): Put on collect_q - skb len: %04x \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) "pdu header and data for up to 32 bytes:\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) __func__, dev->name, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) CTCM_D3_DUMP((char *)skb->data, min_t(int, 32, skb->len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) skb_queue_tail(&ch->collect_queue, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) ch->collect_len += skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) kfree(p_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) spin_unlock_irqrestore(&ch->collect_lock, saveflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) * Protect skb against beeing free'd by upper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * layers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) refcount_inc(&skb->users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * IDAL support in CTCM is broken, so we have to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) * care about skb's above 2G ourselves.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) hi = ((unsigned long)skb->tail + TH_HEADER_LENGTH) >> 31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (hi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) nskb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (!nskb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) goto nomem_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) skb_put_data(nskb, skb->data, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) refcount_inc(&nskb->users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) refcount_dec(&skb->users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) dev_kfree_skb_irq(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) skb = nskb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (!p_header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) goto nomem_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) p_header->pdu_offset = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) p_header->pdu_proto = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) p_header->pdu_flag = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) p_header->pdu_seq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if (be16_to_cpu(skb->protocol) == ETH_P_SNAP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) p_header->pdu_flag |= PDU_FIRST | PDU_CNTL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) p_header->pdu_flag |= PDU_FIRST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) memcpy(skb_push(skb, PDU_HEADER_LENGTH), p_header, PDU_HEADER_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) kfree(p_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (ch->collect_len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) spin_lock_irqsave(&ch->collect_lock, saveflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) skb_queue_tail(&ch->collect_queue, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) ch->collect_len += skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) skb = skb_dequeue(&ch->collect_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) ch->collect_len -= skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) spin_unlock_irqrestore(&ch->collect_lock, saveflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) p_header = (struct pdu *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) p_header->pdu_flag |= PDU_LAST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) ch->prof.txlen += skb->len - PDU_HEADER_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) header = kmalloc(TH_HEADER_LENGTH, gfp_type());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (!header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) goto nomem_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) header->th_seg = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) header->th_ch_flag = TH_HAS_PDU; /* Normal data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) header->th_blk_flag = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) header->th_is_xid = 0x00; /* Just data here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) ch->th_seq_num++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) header->th_seq_num = ch->th_seq_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) CTCM_PR_DBGDATA("%s(%s) ToVTAM_th_seq= %08x\n" ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) __func__, dev->name, ch->th_seq_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) /* put the TH on the packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) memcpy(skb_push(skb, TH_HEADER_LENGTH), header, TH_HEADER_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) kfree(header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) CTCM_PR_DBGDATA("%s(%s): skb len: %04x\n - pdu header and data for "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) "up to 32 bytes sent to vtam:\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) __func__, dev->name, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) CTCM_D3_DUMP((char *)skb->data, min_t(int, 32, skb->len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) ch->ccw[4].count = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) if (set_normalized_cda(&ch->ccw[4], skb->data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) * idal allocation failed, try via copying to trans_skb.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) * trans_skb usually has a pre-allocated idal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if (ctcm_checkalloc_buffer(ch)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * Remove our header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) * It gets added again on retransmit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) goto nomem_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) skb_reset_tail_pointer(ch->trans_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) ch->trans_skb->len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) ch->ccw[1].count = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) skb_put_data(ch->trans_skb, skb->data, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) refcount_dec(&skb->users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) dev_kfree_skb_irq(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) ccw_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) CTCM_PR_DBGDATA("%s(%s): trans_skb len: %04x\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) "up to 32 bytes sent to vtam:\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) __func__, dev->name, ch->trans_skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) CTCM_D3_DUMP((char *)ch->trans_skb->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) min_t(int, 32, ch->trans_skb->len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) skb_queue_tail(&ch->io_queue, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) ccw_idx = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) ch->retry = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) fsm_newstate(ch->fsm, CTC_STATE_TX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (do_debug_ccw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) ctcmpc_dumpit((char *)&ch->ccw[ccw_idx],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) sizeof(struct ccw1) * 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) ch->prof.send_stamp = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) rc = ccw_device_start(ch->cdev, &ch->ccw[ccw_idx], 0, 0xff, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (ccw_idx == 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) ch->prof.doios_single++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) fsm_deltimer(&ch->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) ctcm_ccw_check_rc(ch, rc, "single skb TX");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) if (ccw_idx == 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) skb_dequeue_tail(&ch->io_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) } else if (ccw_idx == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) priv->stats.tx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) priv->stats.tx_bytes += skb->len - TH_HEADER_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (ch->th_seq_num > 0xf0000000) /* Chose at random. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) ctcmpc_send_sweep_req(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) nomem_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_CRIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) "%s(%s): MEMORY allocation ERROR\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) CTCM_FUNTAIL, ch->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) refcount_dec(&skb->users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) dev_kfree_skb_any(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) CTCM_PR_DEBUG("Exit %s(%s)\n", __func__, dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) * Start transmission of a packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) * Called from generic network device layer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) * skb Pointer to buffer containing the packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) * dev Pointer to interface struct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) * returns 0 if packet consumed, !0 if packet rejected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) * Note: If we return !0, then the packet is free'd by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) * the generic network layer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) /* first merge version - leaving both functions separated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) static int ctcm_tx(struct sk_buff *skb, struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) struct ctcm_priv *priv = dev->ml_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) if (skb == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) "%s(%s): NULL sk_buff passed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) CTCM_FUNTAIL, dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) priv->stats.tx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if (skb_headroom(skb) < (LL_HEADER_LENGTH + 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) "%s(%s): Got sk_buff with head room < %ld bytes",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) CTCM_FUNTAIL, dev->name, LL_HEADER_LENGTH + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) priv->stats.tx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) * If channels are not running, try to restart them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * and throw away packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) if (fsm_getstate(priv->fsm) != DEV_STATE_RUNNING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) fsm_event(priv->fsm, DEV_EVENT_START, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) priv->stats.tx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) priv->stats.tx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) priv->stats.tx_carrier_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if (ctcm_test_and_set_busy(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) return NETDEV_TX_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) netif_trans_update(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (ctcm_transmit_skb(priv->channel[CTCM_WRITE], skb) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) return NETDEV_TX_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) /* unmerged MPC variant of ctcm_tx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) struct ctcm_priv *priv = dev->ml_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) struct mpc_group *grp = priv->mpcg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) struct sk_buff *newskb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) * Some sanity checks ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (skb == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) "%s(%s): NULL sk_buff passed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) CTCM_FUNTAIL, dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) priv->stats.tx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) if (skb_headroom(skb) < (TH_HEADER_LENGTH + PDU_HEADER_LENGTH)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) "%s(%s): Got sk_buff with head room < %ld bytes",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) CTCM_FUNTAIL, dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) TH_HEADER_LENGTH + PDU_HEADER_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) CTCM_D3_DUMP((char *)skb->data, min_t(int, 32, skb->len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) len = skb->len + TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) newskb = __dev_alloc_skb(len, gfp_type() | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (!newskb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) "%s: %s: __dev_alloc_skb failed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) __func__, dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) dev_kfree_skb_any(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) priv->stats.tx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) priv->stats.tx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) priv->stats.tx_carrier_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) newskb->protocol = skb->protocol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) skb_reserve(newskb, TH_HEADER_LENGTH + PDU_HEADER_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) skb_put_data(newskb, skb->data, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) dev_kfree_skb_any(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) skb = newskb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) * If channels are not running,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) * notify anybody about a link failure and throw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) * away packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) if ((fsm_getstate(priv->fsm) != DEV_STATE_RUNNING) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) (fsm_getstate(grp->fsm) < MPCG_STATE_XID2INITW)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) dev_kfree_skb_any(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) "%s(%s): inactive MPCGROUP - dropped",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) CTCM_FUNTAIL, dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) priv->stats.tx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) priv->stats.tx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) priv->stats.tx_carrier_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (ctcm_test_and_set_busy(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) "%s(%s): device busy - dropped",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) CTCM_FUNTAIL, dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) dev_kfree_skb_any(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) priv->stats.tx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) priv->stats.tx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) priv->stats.tx_carrier_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) netif_trans_update(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) if (ctcmpc_transmit_skb(priv->channel[CTCM_WRITE], skb) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) "%s(%s): device error - dropped",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) CTCM_FUNTAIL, dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) dev_kfree_skb_any(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) priv->stats.tx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) priv->stats.tx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) priv->stats.tx_carrier_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) ctcm_clear_busy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) ctcm_clear_busy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (do_debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) MPC_DBF_DEV_NAME(TRACE, dev, "exit");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) return NETDEV_TX_OK; /* handle freeing of skb here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) * Sets MTU of an interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) * dev Pointer to interface struct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) * new_mtu The new MTU to use for this interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) * returns 0 on success, -EINVAL if MTU is out of valid range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) * (valid range is 576 .. 65527). If VM is on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) * remote side, maximum MTU is 32760, however this is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) * not checked here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) static int ctcm_change_mtu(struct net_device *dev, int new_mtu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) struct ctcm_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) int max_bufsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) priv = dev->ml_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) max_bufsize = priv->channel[CTCM_READ]->max_bufsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) if (IS_MPC(priv)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (new_mtu > max_bufsize - TH_HEADER_LENGTH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) dev->hard_header_len = TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) if (new_mtu > max_bufsize - LL_HEADER_LENGTH - 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) dev->hard_header_len = LL_HEADER_LENGTH + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) dev->mtu = new_mtu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) * Returns interface statistics of a device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) * dev Pointer to interface struct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) * returns Pointer to stats struct of this interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) static struct net_device_stats *ctcm_stats(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) return &((struct ctcm_priv *)dev->ml_priv)->stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) static void ctcm_free_netdevice(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) struct ctcm_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) struct mpc_group *grp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) "%s(%s)", CTCM_FUNTAIL, dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) priv = dev->ml_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (priv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) grp = priv->mpcg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (grp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) if (grp->fsm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) kfree_fsm(grp->fsm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) dev_kfree_skb(grp->xid_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) dev_kfree_skb(grp->rcvd_xid_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) tasklet_kill(&grp->mpc_tasklet2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) kfree(grp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) priv->mpcg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) if (priv->fsm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) kfree_fsm(priv->fsm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) priv->fsm = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) kfree(priv->xid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) priv->xid = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) * Note: kfree(priv); is done in "opposite" function of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) * allocator function probe_device which is remove_device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) #ifdef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) free_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) static const struct net_device_ops ctcm_netdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) .ndo_open = ctcm_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) .ndo_stop = ctcm_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) .ndo_get_stats = ctcm_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) .ndo_change_mtu = ctcm_change_mtu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) .ndo_start_xmit = ctcm_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) static const struct net_device_ops ctcm_mpc_netdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) .ndo_open = ctcm_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) .ndo_stop = ctcm_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) .ndo_get_stats = ctcm_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) .ndo_change_mtu = ctcm_change_mtu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) .ndo_start_xmit = ctcmpc_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) static void ctcm_dev_setup(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) dev->type = ARPHRD_SLIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) dev->tx_queue_len = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) dev->flags = IFF_POINTOPOINT | IFF_NOARP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) dev->min_mtu = 576;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) dev->max_mtu = 65527;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) * Initialize everything of the net device except the name and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) * channel structs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) struct mpc_group *grp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) if (IS_MPC(priv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) dev = alloc_netdev(0, MPC_DEVICE_GENE, NET_NAME_UNKNOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) ctcm_dev_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) dev = alloc_netdev(0, CTC_DEVICE_GENE, NET_NAME_UNKNOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) ctcm_dev_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) if (!dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) CTCM_DBF_TEXT_(ERROR, CTC_DBF_CRIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) "%s: MEMORY allocation ERROR",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) CTCM_FUNTAIL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) dev->ml_priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) priv->fsm = init_fsm("ctcmdev", dev_state_names, dev_event_names,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) CTCM_NR_DEV_STATES, CTCM_NR_DEV_EVENTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) dev_fsm, dev_fsm_len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) if (priv->fsm == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) CTCMY_DBF_DEV(SETUP, dev, "init_fsm error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) free_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) fsm_newstate(priv->fsm, DEV_STATE_STOPPED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) fsm_settimer(priv->fsm, &priv->restart_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) if (IS_MPC(priv)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) /* MPC Group Initializations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) grp = ctcmpc_init_mpc_group(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) if (grp == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) MPC_DBF_DEV(SETUP, dev, "init_mpc_group error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) free_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) tasklet_init(&grp->mpc_tasklet2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) mpc_group_ready, (unsigned long)dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) dev->mtu = MPC_BUFSIZE_DEFAULT -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) TH_HEADER_LENGTH - PDU_HEADER_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) dev->netdev_ops = &ctcm_mpc_netdev_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) dev->hard_header_len = TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) priv->buffer_size = MPC_BUFSIZE_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) dev->mtu = CTCM_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) dev->netdev_ops = &ctcm_netdev_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) dev->hard_header_len = LL_HEADER_LENGTH + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) CTCMY_DBF_DEV(SETUP, dev, "finished");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) return dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) * Main IRQ handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) * cdev The ccw_device the interrupt is for.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) * intparm interruption parameter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) * irb interruption response block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) static void ctcm_irq_handler(struct ccw_device *cdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) unsigned long intparm, struct irb *irb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) struct channel *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) struct ctcm_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) struct ccwgroup_device *cgdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) int cstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) int dstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) "Enter %s(%s)", CTCM_FUNTAIL, dev_name(&cdev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) if (ctcm_check_irb_error(cdev, irb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) cgdev = dev_get_drvdata(&cdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) cstat = irb->scsw.cmd.cstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) dstat = irb->scsw.cmd.dstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) /* Check for unsolicited interrupts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) if (cgdev == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) CTCM_DBF_TEXT_(TRACE, CTC_DBF_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) "%s(%s) unsolicited irq: c-%02x d-%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) CTCM_FUNTAIL, dev_name(&cdev->dev), cstat, dstat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) dev_warn(&cdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) "The adapter received a non-specific IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) priv = dev_get_drvdata(&cgdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) /* Try to extract channel from driver data. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) if (priv->channel[CTCM_READ]->cdev == cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) ch = priv->channel[CTCM_READ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) else if (priv->channel[CTCM_WRITE]->cdev == cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) ch = priv->channel[CTCM_WRITE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) dev_err(&cdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) "%s: Internal error: Can't determine channel for "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) "interrupt device %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) __func__, dev_name(&cdev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) /* Explain: inconsistent internal structures */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) dev = ch->netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) if (dev == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) dev_err(&cdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) "%s Internal error: net_device is NULL, ch = 0x%p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) __func__, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) /* Explain: inconsistent internal structures */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) /* Copy interruption response block. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) memcpy(ch->irb, irb, sizeof(struct irb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) /* Issue error message and return on subchannel error code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) if (irb->scsw.cmd.cstat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) fsm_event(ch->fsm, CTC_EVENT_SC_UNKNOWN, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) "%s(%s): sub-ch check %s: cs=%02x ds=%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) CTCM_FUNTAIL, dev->name, ch->id, cstat, dstat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) dev_warn(&cdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) "A check occurred on the subchannel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) /* Check the reason-code of a unit check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) if ((irb->ecw[0] & ch->sense_rc) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) /* print it only once */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) "%s(%s): sense=%02x, ds=%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) CTCM_FUNTAIL, ch->id, irb->ecw[0], dstat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) ccw_unit_check(ch, irb->ecw[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) if (irb->scsw.cmd.dstat & DEV_STAT_BUSY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) fsm_event(ch->fsm, CTC_EVENT_ATTNBUSY, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) fsm_event(ch->fsm, CTC_EVENT_BUSY, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) fsm_event(ch->fsm, CTC_EVENT_ATTN, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) if ((irb->scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) (irb->scsw.cmd.stctl == SCSW_STCTL_STATUS_PEND) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) (irb->scsw.cmd.stctl ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) fsm_event(ch->fsm, CTC_EVENT_FINSTAT, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) fsm_event(ch->fsm, CTC_EVENT_IRQ, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) static const struct device_type ctcm_devtype = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) .name = "ctcm",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) .groups = ctcm_attr_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) * Add ctcm specific attributes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) * Add ctcm private data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) * cgdev pointer to ccwgroup_device just added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) * returns 0 on success, !0 on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) static int ctcm_probe_device(struct ccwgroup_device *cgdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) struct ctcm_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) "%s %p",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) __func__, cgdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) if (!get_device(&cgdev->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) priv = kzalloc(sizeof(struct ctcm_priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) if (!priv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) "%s: memory allocation failure",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) CTCM_FUNTAIL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) put_device(&cgdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) priv->buffer_size = CTCM_BUFSIZE_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) cgdev->cdev[0]->handler = ctcm_irq_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) cgdev->cdev[1]->handler = ctcm_irq_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) dev_set_drvdata(&cgdev->dev, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) cgdev->dev.type = &ctcm_devtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) * Add a new channel to the list of channels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) * Keeps the channel list sorted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) * cdev The ccw_device to be added.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) * type The type class of the new channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) * priv Points to the private data of the ccwgroup_device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) * returns 0 on success, !0 on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) static int add_channel(struct ccw_device *cdev, enum ctcm_channel_types type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) struct ctcm_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) struct channel **c = &channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) struct channel *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) int ccw_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) "%s(%s), type %d, proto %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) __func__, dev_name(&cdev->dev), type, priv->protocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) ch = kzalloc(sizeof(struct channel), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) if (ch == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) ch->protocol = priv->protocol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) if (IS_MPC(priv)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) ch->discontact_th = kzalloc(TH_HEADER_LENGTH, gfp_type());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) if (ch->discontact_th == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) goto nomem_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) ch->discontact_th->th_blk_flag = TH_DISCONTACT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) tasklet_init(&ch->ch_disc_tasklet,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) mpc_action_send_discontact, (unsigned long)ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) tasklet_init(&ch->ch_tasklet, ctcmpc_bh, (unsigned long)ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) ch->max_bufsize = (MPC_BUFSIZE_DEFAULT - 35);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) ccw_num = 17;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) ccw_num = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) ch->ccw = kcalloc(ccw_num, sizeof(struct ccw1), GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) if (ch->ccw == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) goto nomem_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) ch->cdev = cdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) snprintf(ch->id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) ch->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) * "static" ccws are used in the following way:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) * ccw[0..2] (Channel program for generic I/O):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) * 0: prepare
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) * 1: read or write (depending on direction) with fixed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) * buffer (idal allocated once when buffer is allocated)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) * 2: nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) * ccw[3..5] (Channel program for direct write of packets)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) * 3: prepare
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) * 4: write (idal allocated on every write).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) * 5: nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) * ccw[6..7] (Channel program for initial channel setup):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) * 6: set extended mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) * 7: nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) * ch->ccw[0..5] are initialized in ch_action_start because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) * the channel's direction is yet unknown here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) * ccws used for xid2 negotiations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) * ch-ccw[8-14] need to be used for the XID exchange either
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) * X side XID2 Processing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) * 8: write control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) * 9: write th
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) * 10: write XID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) * 11: read th from secondary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) * 12: read XID from secondary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) * 13: read 4 byte ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) * 14: nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) * Y side XID Processing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) * 8: sense
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) * 9: read th
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) * 10: read XID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) * 11: write th
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) * 12: write XID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) * 13: write 4 byte ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) * 14: nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) * ccws used for double noop due to VM timing issues
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) * which result in unrecoverable Busy on channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) * 15: nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) * 16: nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) ch->ccw[6].cmd_code = CCW_CMD_SET_EXTENDED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) ch->ccw[6].flags = CCW_FLAG_SLI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) ch->ccw[7].cmd_code = CCW_CMD_NOOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) ch->ccw[7].flags = CCW_FLAG_SLI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) if (IS_MPC(priv)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) ch->ccw[15].cmd_code = CCW_CMD_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) ch->ccw[15].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) ch->ccw[15].count = TH_HEADER_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) ch->ccw[15].cda = virt_to_phys(ch->discontact_th);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) ch->ccw[16].cmd_code = CCW_CMD_NOOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) ch->ccw[16].flags = CCW_FLAG_SLI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) ch->fsm = init_fsm(ch->id, ctc_ch_state_names,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) ctc_ch_event_names, CTC_MPC_NR_STATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) CTC_MPC_NR_EVENTS, ctcmpc_ch_fsm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) mpc_ch_fsm_len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) ch->fsm = init_fsm(ch->id, ctc_ch_state_names,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) ctc_ch_event_names, CTC_NR_STATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) CTC_NR_EVENTS, ch_fsm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) ch_fsm_len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) if (ch->fsm == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) goto nomem_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) fsm_newstate(ch->fsm, CTC_STATE_IDLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) ch->irb = kzalloc(sizeof(struct irb), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) if (ch->irb == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) goto nomem_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) while (*c && ctcm_less_than((*c)->id, ch->id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) c = &(*c)->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) if (*c && (!strncmp((*c)->id, ch->id, CTCM_ID_SIZE))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) "%s (%s) already in list, using old entry",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) __func__, (*c)->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) goto free_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) spin_lock_init(&ch->collect_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) fsm_settimer(ch->fsm, &ch->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) skb_queue_head_init(&ch->io_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) skb_queue_head_init(&ch->collect_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) if (IS_MPC(priv)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) fsm_settimer(ch->fsm, &ch->sweep_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) skb_queue_head_init(&ch->sweep_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) ch->next = *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) *c = ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) nomem_return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) free_return: /* note that all channel pointers are 0 or valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) kfree(ch->ccw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) kfree(ch->discontact_th);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) kfree_fsm(ch->fsm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) kfree(ch->irb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) kfree(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) * Return type of a detected device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) static enum ctcm_channel_types get_channel_type(struct ccw_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) enum ctcm_channel_types type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) type = (enum ctcm_channel_types)id->driver_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) if (type == ctcm_channel_type_ficon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) type = ctcm_channel_type_escon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) return type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) * Setup an interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) * cgdev Device to be setup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) * returns 0 on success, !0 on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) static int ctcm_new_device(struct ccwgroup_device *cgdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) char read_id[CTCM_ID_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) char write_id[CTCM_ID_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) int direction;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) enum ctcm_channel_types type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) struct ctcm_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) struct ccw_device *cdev0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) struct ccw_device *cdev1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) struct channel *readc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) struct channel *writec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) priv = dev_get_drvdata(&cgdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) if (!priv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) result = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) goto out_err_result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) cdev0 = cgdev->cdev[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) cdev1 = cgdev->cdev[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) type = get_channel_type(&cdev0->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) snprintf(read_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev0->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) snprintf(write_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev1->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) ret = add_channel(cdev0, type, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) result = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) goto out_err_result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) ret = add_channel(cdev1, type, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) result = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) goto out_remove_channel1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) ret = ccw_device_set_online(cdev0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) "%s(%s) set_online rc=%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) CTCM_FUNTAIL, read_id, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) result = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) goto out_remove_channel2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) ret = ccw_device_set_online(cdev1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) "%s(%s) set_online rc=%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) CTCM_FUNTAIL, write_id, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) result = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) goto out_ccw1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) dev = ctcm_init_netdevice(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) if (dev == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) result = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) goto out_ccw2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) for (direction = CTCM_READ; direction <= CTCM_WRITE; direction++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) priv->channel[direction] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) channel_get(type, direction == CTCM_READ ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) read_id : write_id, direction);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) if (priv->channel[direction] == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) if (direction == CTCM_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) channel_free(priv->channel[CTCM_READ]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) result = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) goto out_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) priv->channel[direction]->netdev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) priv->channel[direction]->protocol = priv->protocol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) priv->channel[direction]->max_bufsize = priv->buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) /* sysfs magic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) SET_NETDEV_DEV(dev, &cgdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) if (register_netdev(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) result = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) goto out_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) dev_info(&dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) "setup OK : r/w = %s/%s, protocol : %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) priv->channel[CTCM_READ]->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) priv->channel[CTCM_WRITE]->id, priv->protocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) "setup(%s) OK : r/w = %s/%s, protocol : %d", dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) priv->channel[CTCM_READ]->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) priv->channel[CTCM_WRITE]->id, priv->protocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) out_dev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) ctcm_free_netdevice(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) out_ccw2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) ccw_device_set_offline(cgdev->cdev[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) out_ccw1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) ccw_device_set_offline(cgdev->cdev[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) out_remove_channel2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) readc = channel_get(type, read_id, CTCM_READ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) channel_remove(readc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) out_remove_channel1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) writec = channel_get(type, write_id, CTCM_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) channel_remove(writec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) out_err_result:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) * Shutdown an interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) * cgdev Device to be shut down.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) * returns 0 on success, !0 on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) static int ctcm_shutdown_device(struct ccwgroup_device *cgdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) struct ctcm_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) priv = dev_get_drvdata(&cgdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) if (priv->channel[CTCM_READ]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) dev = priv->channel[CTCM_READ]->netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) CTCM_DBF_DEV(SETUP, dev, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) /* Close the device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) ctcm_close(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) dev->flags &= ~IFF_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) channel_free(priv->channel[CTCM_READ]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) if (priv->channel[CTCM_WRITE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) channel_free(priv->channel[CTCM_WRITE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) if (dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) unregister_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) ctcm_free_netdevice(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) if (priv->fsm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) kfree_fsm(priv->fsm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) ccw_device_set_offline(cgdev->cdev[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) ccw_device_set_offline(cgdev->cdev[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) channel_remove(priv->channel[CTCM_READ]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) channel_remove(priv->channel[CTCM_WRITE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) priv->channel[CTCM_READ] = priv->channel[CTCM_WRITE] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) static void ctcm_remove_device(struct ccwgroup_device *cgdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) struct ctcm_priv *priv = dev_get_drvdata(&cgdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) "removing device %p, proto : %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) cgdev, priv->protocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) if (cgdev->state == CCWGROUP_ONLINE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) ctcm_shutdown_device(cgdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) dev_set_drvdata(&cgdev->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) kfree(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) put_device(&cgdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) static struct ccw_device_id ctcm_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) {CCW_DEVICE(0x3088, 0x08), .driver_info = ctcm_channel_type_parallel},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) {CCW_DEVICE(0x3088, 0x1e), .driver_info = ctcm_channel_type_ficon},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) {CCW_DEVICE(0x3088, 0x1f), .driver_info = ctcm_channel_type_escon},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) MODULE_DEVICE_TABLE(ccw, ctcm_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) static struct ccw_driver ctcm_ccw_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) .name = "ctcm",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) .ids = ctcm_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) .probe = ccwgroup_probe_ccwdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) .remove = ccwgroup_remove_ccwdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) .int_class = IRQIO_CTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) static struct ccwgroup_driver ctcm_group_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) .name = CTC_DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) .ccw_driver = &ctcm_ccw_driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) .setup = ctcm_probe_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) .remove = ctcm_remove_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) .set_online = ctcm_new_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) .set_offline = ctcm_shutdown_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) static ssize_t group_store(struct device_driver *ddrv, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) err = ccwgroup_create_dev(ctcm_root_dev, &ctcm_group_driver, 2, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) return err ? err : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) static DRIVER_ATTR_WO(group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) static struct attribute *ctcm_drv_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) &driver_attr_group.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) static struct attribute_group ctcm_drv_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) .attrs = ctcm_drv_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) static const struct attribute_group *ctcm_drv_attr_groups[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) &ctcm_drv_attr_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) * Module related routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) * Prepare to be unloaded. Free IRQ's and release all resources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) * This is called just before this module is unloaded. It is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) * not called, if the usage count is !0, so we don't need to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) * for that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) static void __exit ctcm_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) ccwgroup_driver_unregister(&ctcm_group_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) ccw_driver_unregister(&ctcm_ccw_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) root_device_unregister(ctcm_root_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) ctcm_unregister_dbf_views();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) pr_info("CTCM driver unloaded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) * Print Banner.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) static void print_banner(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) pr_info("CTCM driver initialized\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) * Initialize module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) * This is called just after the module is loaded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) * returns 0 on success, !0 on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) static int __init ctcm_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) channels = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) ret = ctcm_register_dbf_views();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) ctcm_root_dev = root_device_register("ctcm");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) ret = PTR_ERR_OR_ZERO(ctcm_root_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) goto register_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) ret = ccw_driver_register(&ctcm_ccw_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) goto ccw_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) ctcm_group_driver.driver.groups = ctcm_drv_attr_groups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) ret = ccwgroup_driver_register(&ctcm_group_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) goto ccwgroup_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) print_banner();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) ccwgroup_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) ccw_driver_unregister(&ctcm_ccw_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) ccw_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) root_device_unregister(ctcm_root_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) register_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) ctcm_unregister_dbf_views();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) pr_err("%s / Initializing the ctcm device driver failed, ret = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) module_init(ctcm_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) module_exit(ctcm_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) MODULE_AUTHOR("Peter Tiedemann <ptiedem@de.ibm.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) MODULE_DESCRIPTION("Network driver for S/390 CTC + CTCMPC (SNA)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828)