Example #1
0
static ssize_t dump_rb_frame(char *buf, size_t size, struct sbd_ring_buffer *rb)
{
    int idx;
    u32 i, j, nr, nc, len = 0;

    nr = min_t(u32, rb->len, sipc_ps_ch(rb->ch) ? 48 : 32);

    /* 52 Bytes = ip header(20) + TCP header(32) */
    nc = sipc_ps_ch(rb->ch) ? 52 : 16;

    /* dumps recent n frames */
    for (i = 0; i < nr; i++) {
        idx = *rb->wp - i - 1;
        if (idx < 0)
            idx = rb->len + idx;
        /*
        len += snprintf((buf + len), (size - len), "rb[%03d] ", idx);
        */
        for (j = 0; j < nc; j++)
            len += snprintf((buf + len), (size - len),
                            "%02x", rb->buff[idx][j]);

        len += snprintf((buf + len), (size - len), "\n");
    }

    return len;
}
static int rx_frames_from_dev(struct mem_link_device *mld,
			      struct mem_ipc_device *dev)
{
	struct link_device *ld = &mld->link_dev;
	struct sk_buff_head *skb_rxq = dev->skb_rxq;
	unsigned int qsize = get_rxq_buff_size(dev);
	unsigned int in = get_rxq_head(dev);
	unsigned int out = get_rxq_tail(dev);
	unsigned int size = circ_get_usage(qsize, in, out);
	int rcvd = 0;

	if (unlikely(circ_empty(in, out)))
		return 0;

	while (rcvd < size) {
		struct sk_buff *skb;
		u8 ch;
		struct io_device *iod;

		skb = rxq_read(mld, dev, in);
		if (!skb)
			break;

		ch = sipc5_get_ch(skb->data);
		iod = link_get_iod_with_channel(ld, ch);
		if (!iod) {
			mif_err("%s: ERR! No IOD for CH.%d\n", ld->name, ch);
			dev_kfree_skb_any(skb);
			mem_forced_cp_crash(mld);
			break;
		}

		/* Record the IO device and the link device into the &skb->cb */
		skbpriv(skb)->iod = iod;
		skbpriv(skb)->ld = ld;

		skbpriv(skb)->lnk_hdr = iod->link_header;
		skbpriv(skb)->sipc_ch = ch;

		/* The $rcvd must be accumulated here, because $skb can be freed
		   in pass_skb_to_demux(). */
		rcvd += skb->len;

		if (likely(sipc_ps_ch(ch)))
			skb_queue_tail(skb_rxq, skb);
		else
			pass_skb_to_demux(mld, skb);
	}

	if (rcvd < size) {
		struct link_device *ld = &mld->link_dev;
		mif_err("%s: WARN! rcvd %d < size %d\n", ld->name, rcvd, size);
	}

	return rcvd;
}
static void recv_sbd_ipc_frames(struct mem_link_device *mld,
				struct mem_snapshot *mst)
{
	struct sbd_link_device *sl = &mld->sbd_link_dev;
	int i;

	for (i = 0; i < sl->num_channels; i++) {
		struct sbd_ring_buffer *rb = sbd_id2rb(sl, i, RX);

		if (unlikely(rb_empty(rb)))
			continue;

		if (likely(sipc_ps_ch(rb->ch)))
			rx_net_frames_from_rb(rb);
		else
			rx_ipc_frames_from_rb(rb);
	}
}
static int tx_frames_to_rb(struct sbd_ring_buffer *rb)
{
	struct sk_buff_head *skb_txq = &rb->skb_q;
	int tx_bytes = 0;
	int ret = 0;

	while (1) {
		struct sk_buff *skb;
#ifdef DEBUG_MODEM_IF
		u8 *hdr;
#endif

		skb = skb_dequeue(skb_txq);
		if (unlikely(!skb))
			break;

		ret = sbd_pio_tx(rb, skb);
		if (unlikely(ret < 0)) {
			/* Take the skb back to the skb_txq */
			skb_queue_head(skb_txq, skb);
			break;
		}

		tx_bytes += ret;

#ifdef DEBUG_MODEM_IF
		hdr = skbpriv(skb)->lnk_hdr ? skb->data : NULL;
#ifdef DEBUG_MODEM_IF_IP_DATA
		if (sipc_ps_ch(rb->ch)) {
			u8 *ip_pkt = skb->data;
			if (hdr)
				ip_pkt += sipc5_get_hdr_len(hdr);
			print_ipv4_packet(ip_pkt, TX);
		}
#endif
#ifdef DEBUG_MODEM_IF_LINK_TX
		log_ipc_pkt(rb->ch, LINK, TX, skb, hdr);
#endif
#endif
		dev_kfree_skb_any(skb);
	}

	return (ret < 0) ? ret : tx_bytes;
}
/**
@brief		extract all IPC link frames from a circular queue

In a while loop,\n
1) Receives each IPC link frame stored in the @b @@dev RXQ.\n
2) If the frame is a PS (network) data frame, stores it to an skb_rxq and
   schedules a delayed work for PS data reception.\n
3) Otherwise, passes it to the DEMUX layer immediately.\n

@param mld	the pointer to a mem_link_device instance
@param dev	the pointer to a mem_ipc_device instance (IPC_FMT, etc.)

@retval "> 0"	if valid data received
@retval "= 0"	if no data received
@retval "< 0"	if ANY error
*/
static int rx_frames_from_dev(struct mem_link_device *mld,
			      struct mem_ipc_device *dev)
{
	struct sk_buff_head *skb_rxq = dev->skb_rxq;
	unsigned int qsize = get_rxq_buff_size(dev);
	unsigned int in = get_rxq_head(dev);
	unsigned int out = get_rxq_tail(dev);
	unsigned int size = circ_get_usage(qsize, in, out);
	int rcvd = 0;

	if (unlikely(circ_empty(in, out)))
		return 0;

	while (rcvd < size) {
		struct sk_buff *skb;

		skb = rxq_read(mld, dev, in);
		if (!skb)
			break;

		/* The $rcvd must be accumulated here, because $skb can be freed
		   in pass_skb_to_demux(). */
		rcvd += skb->len;

		if (likely(sipc_ps_ch(sipc5_get_ch_id(skb->data))))
			skb_queue_tail(skb_rxq, skb);
		else
			pass_skb_to_demux(mld, skb);
	}

#ifdef DEBUG_MODEM_IF
	if (rcvd < size) {
		struct link_device *ld = &mld->link_dev;
		mif_err("%s: WARN! rcvd %d < size %d\n", ld->name, rcvd, size);
	}
#endif

	return rcvd;
}
static inline bool log_enabled(u8 ch, enum ipc_layer layer)
{
	if (unlikely(layer == IOD_RX || layer == IOD_TX))
		if (unlikely(!test_bit(DEBUG_FLAG_IOD, &dflags)))
			return false;

	if (sipc5_fmt_ch(ch))
		return test_bit(DEBUG_FLAG_FMT, &dflags);
	else if (sipc_ps_ch(ch))
		return test_bit(DEBUG_FLAG_PS, &dflags);
	else if (sipc5_rfs_ch(ch))
		return test_bit(DEBUG_FLAG_RFS, &dflags);
	else if (sipc_csd_ch(ch))
		return test_bit(DEBUG_FLAG_CSVT, &dflags);
	else if (sipc_log_ch(ch))
		return test_bit(DEBUG_FLAG_LOG, &dflags);
	else if (sipc5_boot_ch(ch))
		return test_bit(DEBUG_FLAG_BOOT, &dflags);
	else if (sipc5_dump_ch(ch))
		return test_bit(DEBUG_FLAG_DUMP, &dflags);
	else
		return false;
}
Example #7
0
/**
@brief		receive all @b IPC message frames in all RXQs

In a for loop,\n
1) Checks any REQ_ACK received.\n
2) Receives all IPC link frames in every RXQ.\n
3) Sends RES_ACK if there was REQ_ACK from CP.\n
4) Checks any RES_ACK received.\n

@param mld	the pointer to a mem_link_device instance
@param mst	the pointer to a mem_snapshot instance
*/
void recv_sbd_ipc_frames(struct mem_link_device *mld)
{
	struct sbd_link_device *sl = &mld->sbd_link_dev;
	int i;

	for (i = 0; i < sl->num_channels; i++) {
		struct sbd_ring_buffer *rb = sbd_id2rb(sl, i, RX);

		if (unlikely(rb_empty(rb)))
			continue;

		if (likely(sipc_ps_ch(rb->ch))) {
#ifdef CONFIG_LINK_DEVICE_NAPI
			//mld->link_dev.disable_irq(&mld->link_dev);
			if (napi_schedule_prep(&rb->iod->napi))
				__napi_schedule(&rb->iod->napi);
#else
			rx_net_frames_from_rb(rb, 0);
#endif
		} else {
			rx_ipc_frames_from_rb(rb);
		}
	}
}