drivers/s390/net/ctcm_fsms.c

Source file repositories/reference/linux-study-clean/drivers/s390/net/ctcm_fsms.c

File Facts

System
Linux kernel
Corpus path
drivers/s390/net/ctcm_fsms.c
Extension
.c
Size
75315 bytes
Lines
2299
Domain
Driver Families
Bucket
drivers/s390
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (first) {
			priv->stats.tx_bytes += 2;
			first = 0;
		}
		refcount_dec(&skb->users);
		dev_kfree_skb_irq(skb);
	}
	spin_lock(&ch->collect_lock);
	clear_normalized_cda(&ch->ccw[4]);
	if (ch->collect_len > 0) {
		int rc;

		if (ctcm_checkalloc_buffer(ch)) {
			spin_unlock(&ch->collect_lock);
			return;
		}
		ch->trans_skb->data = ch->trans_skb_data;
		skb_reset_tail_pointer(ch->trans_skb);
		ch->trans_skb->len = 0;
		if (ch->prof.maxmulti < (ch->collect_len + 2))
			ch->prof.maxmulti = ch->collect_len + 2;
		if (ch->prof.maxcqueue < skb_queue_len(&ch->collect_queue))
			ch->prof.maxcqueue = skb_queue_len(&ch->collect_queue);
		*((__u16 *)skb_put(ch->trans_skb, 2)) = ch->collect_len + 2;
		i = 0;
		while ((skb = skb_dequeue(&ch->collect_queue))) {
			skb_copy_from_linear_data(skb,
				skb_put(ch->trans_skb, skb->len), skb->len);
			priv->stats.tx_packets++;
			priv->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;
			refcount_dec(&skb->users);
			dev_kfree_skb_irq(skb);
			i++;
		}
		ch->collect_len = 0;
		spin_unlock(&ch->collect_lock);
		ch->ccw[1].count = ch->trans_skb->len;
		fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
		ch->prof.send_stamp = jiffies;
		rc = ccw_device_start(ch->cdev, &ch->ccw[0], 0, 0xff, 0);
		ch->prof.doios_multi++;
		if (rc != 0) {
			priv->stats.tx_dropped += i;
			priv->stats.tx_errors += i;
			fsm_deltimer(&ch->timer);
			ctcm_ccw_check_rc(ch, rc, "chained TX");
		}
	} else {
		spin_unlock(&ch->collect_lock);
		fsm_newstate(fi, CTC_STATE_TXIDLE);
	}
	ctcm_clear_busy_do(dev);
}

/*
 * Initial data is sent.
 * Notify device statemachine that we are up and
 * running.
 *
 * fi		An instance of a channel statemachine.
 * event	The event, just happened.
 * arg		Generic pointer, casted from channel * upon call.
 */
void ctcm_chx_txidle(fsm_instance *fi, int event, void *arg)
{
	struct channel *ch = arg;
	struct net_device *dev = ch->netdev;
	struct ctcm_priv *priv = dev->ml_priv;

	CTCM_PR_DEBUG("%s(%s): %s\n", __func__, ch->id, dev->name);

	fsm_deltimer(&ch->timer);
	fsm_newstate(fi, CTC_STATE_TXIDLE);
	fsm_event(priv->fsm, DEV_EVENT_TXUP, ch->netdev);
}

/*
 * Got normal data, check for sanity, queue it up, allocate new buffer
 * trigger bottom half, and initiate next read.
 *
 * fi		An instance of a channel statemachine.
 * event	The event, just happened.
 * arg		Generic pointer, casted from channel * upon call.
 */
static void chx_rx(fsm_instance *fi, int event, void *arg)
{
	struct channel *ch = arg;
	struct net_device *dev = ch->netdev;
	struct ctcm_priv *priv = dev->ml_priv;
	int len = ch->max_bufsize - ch->irb->scsw.cmd.count;

Annotation

Implementation Notes