[svn-commits] tzafrir: branch linux/2.5 r10394 - /linux/branches/2.5/drivers/dahdi/xpp/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Jan 3 08:44:41 CST 2012


Author: tzafrir
Date: Tue Jan  3 08:44:37 2012
New Revision: 10394

URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=10394
Log:
xpp: BRI: batch D-Channel packets to fix frag.

* We need to split the BRI D-Channel (HDLC) frames to smaller packets,
  limitation of the FPGA.
* This changes batches BRI D-channel packets of the same HDLC frame to a
  single XPP frame.
* Avoids an accidental fragmantion in case we were delayed for a few ms-s.
* Also improves efficiency.

Signed-off-by: Oron Peled <oron.peled at xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen at xorcom.com>

Modified:
    linux/branches/2.5/drivers/dahdi/xpp/card_bri.c

Modified: linux/branches/2.5/drivers/dahdi/xpp/card_bri.c
URL: http://svnview.digium.com/svn/dahdi/linux/branches/2.5/drivers/dahdi/xpp/card_bri.c?view=diff&rev=10394&r1=10393&r2=10394
==============================================================================
--- linux/branches/2.5/drivers/dahdi/xpp/card_bri.c (original)
+++ linux/branches/2.5/drivers/dahdi/xpp/card_bri.c Tue Jan  3 08:44:37 2012
@@ -208,7 +208,6 @@
 	 * D-Chan: buffers + extra state info.
 	 */
 	atomic_t			hdlc_pending;
-	byte				dchan_tbuf[DCHAN_BUFSIZE];
 	bool				txframe_begin;
 
 	uint				tick_counter;
@@ -514,90 +513,125 @@
 	}
 }
 
-int send_multibyte_request(xbus_t *xbus,
-	unsigned unit, xportno_t portno,
-	bool eoftx, byte *buf, unsigned len)
-{
-	xframe_t	*xframe;
-	xpacket_t	*pack;
-	reg_cmd_t	*reg_cmd;
-	int		ret;
-
-	if (!len) {
-		PORT_ERR(xbus, unit, portno,
-			"%s: zero length request. dropping.\n", __func__);
-		return -EINVAL;
-	}
-	if (len > MULTIBYTE_MAX_LEN) {
-		PORT_ERR(xbus, unit, portno,
-			"%s: len=%d is too long. dropping.\n", __func__, len);
-		return -EINVAL;
-	}
-	XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, unit);
+static int send_dchan_frame(xpd_t *xpd, xframe_t *xframe, bool is_eof)
+{
+	struct BRI_priv_data *priv;
+	int ret;
+
+	XPD_DBG(COMMANDS, xpd, "eoframe=%d\n", is_eof);
+	priv = xpd->priv;
+	if (!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags)
+			&& !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) {
+		XPD_DBG(SIGNAL, xpd, "Want to transmit: Kick D-Channel transmiter\n");
+		if (!IS_NT(xpd))
+			te_activation(xpd, 1);
+		else
+			nt_activation(xpd, 1);
+	}
+	dump_xframe("send_dchan_frame", xpd->xbus, xframe, debug);
+	ret = send_cmd_frame(xpd->xbus, xframe);
+	if (ret < 0)
+		XPD_ERR(xpd, "%s: failed sending xframe\n", __func__);
+	if (is_eof) {
+		atomic_dec(&priv->hdlc_pending);
+		priv->dchan_tx_counter++;
+		priv->txframe_begin = 1;
+	} else
+		priv->txframe_begin = 0;
+	priv->dchan_notx_ticks = 0;
+	return ret;
+}
+
+/*
+ * Fill a single multibyte REGISTER_REQUEST
+ */
+static void fill_multibyte(xpd_t *xpd, xpacket_t *pack, bool eoframe,
+		char *buf, int len)
+{
+	reg_cmd_t *reg_cmd;
+	char *p;
+
+	XPACKET_INIT(pack, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx, 0, 0);
+	XPACKET_LEN(pack) = RPACKET_SIZE(GLOBAL, REGISTER_REQUEST);
 	reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
 	reg_cmd->bytes = len;
 	reg_cmd->is_multibyte = 1;
-	reg_cmd->portnum = portno;
-	reg_cmd->eoframe = eoftx;
-	memcpy(REG_XDATA(reg_cmd), (byte *)buf, len);
-	if (debug & DBG_REGS)
-		dump_xframe(__func__, xbus, xframe, debug);
-	ret = send_cmd_frame(xbus, xframe);
-	if (ret < 0)
-		PORT_ERR(xbus, unit, portno,
-			"%s: failed sending xframe\n", __func__);
-	return ret;
-}
-
+	reg_cmd->portnum = xpd->addr.subunit;
+	reg_cmd->eoframe = eoframe;
+	p = REG_XDATA(reg_cmd);
+	memcpy(p, buf, len);
+	if (debug)
+		dump_dchan_packet(xpd, 1, p, len);
+}
+
+/*
+ * Transmit available D-Channel frames
+ *
+ * - FPGA firmware expect to get this as a sequence of REGISTER_REQUEST
+ *   multibyte commands.
+ * - The payload of each command is limited to MULTIBYTE_MAX_LEN bytes.
+ * - We batch several REGISTER_REQUEST packets into a single xframe.
+ * - The xframe is terminated when we get a bri "end of frame"
+ *   or when the xframe is full (should not happen).
+ */
 static int tx_dchan(xpd_t *xpd)
 {
-	struct BRI_priv_data	*priv;
-	struct dahdi_chan	*dchan;
-	int			len;
-	int			eoframe;
-	int			ret;
-
-	priv = xpd->priv;
-	BUG_ON(!priv);
-	if(atomic_read(&priv->hdlc_pending) == 0)
+	struct BRI_priv_data *priv;
+	xframe_t *xframe;
+	xpacket_t *pack;
+	int packet_count;
+	int eoframe;
+	int ret;
+
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	if (atomic_read(&priv->hdlc_pending) == 0)
 		return 0;
-	if(!SPAN_REGISTERED(xpd) || !(PHONEDEV(xpd).span.flags & DAHDI_FLAG_RUNNING))
+	if (!SPAN_REGISTERED(xpd) ||
+			!(PHONEDEV(xpd).span.flags & DAHDI_FLAG_RUNNING))
 		return 0;
-	dchan = XPD_CHAN(xpd, 2);
-	len = ARRAY_SIZE(priv->dchan_tbuf);
-	if(len > MULTIBYTE_MAX_LEN)
-		len = MULTIBYTE_MAX_LEN;
-	eoframe = dahdi_hdlc_getbuf(dchan, priv->dchan_tbuf, &len);
-	if(len <= 0)
-		return 0; /* Nothing to transmit on D channel */
-	if(len > MULTIBYTE_MAX_LEN) {
-		XPD_ERR(xpd, "%s: len=%d. need to split. Unimplemented.\n", __FUNCTION__, len);
-		dump_hex_buf(xpd, "D-Chan TX:", priv->dchan_tbuf, len);
-		return -EINVAL;
-	}
-	if(!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags) && !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) {
-		XPD_DBG(SIGNAL, xpd, "Want to transmit: Kick D-Channel transmiter\n");
-		if(! IS_NT(xpd))
-			te_activation(xpd, 1);
-		else
-			nt_activation(xpd, 1);
-	}
-	if(debug)
-		dump_dchan_packet(xpd, 1, priv->dchan_tbuf, len);
-	if(eoframe)
-		priv->txframe_begin = 1;
-	else
-		priv->txframe_begin = 0;
-	XPD_DBG(COMMANDS, xpd, "eoframe=%d len=%d\n", eoframe, len);
-	ret = send_multibyte_request(xpd->xbus, xpd->addr.unit, xpd->addr.subunit,
-			eoframe, priv->dchan_tbuf, len);
-	if(ret < 0)
-		XPD_NOTICE(xpd, "%s: failed sending xframe\n", __FUNCTION__);
-	if(eoframe) {
-		atomic_dec(&priv->hdlc_pending);
-		priv->dchan_tx_counter++;
-	}
-	priv->dchan_notx_ticks = 0;
+	/* Allocate frame */
+	xframe = ALLOC_SEND_XFRAME(xpd->xbus);
+	if (!xframe) {
+		XPD_NOTICE(xpd, "%s: failed to allocate new xframe\n",
+			__func__);
+		return -ENOMEM;
+	}
+	for (packet_count = 0, eoframe = 0; !eoframe; packet_count++) {
+		int packet_len = RPACKET_SIZE(GLOBAL, REGISTER_REQUEST);
+		char buf[MULTIBYTE_MAX_LEN];
+		int len = MULTIBYTE_MAX_LEN;
+
+		/* Reserve packet */
+		pack = xframe_next_packet(xframe, packet_len);
+		if (!pack) {
+			BUG_ON(!packet_count);
+			/*
+			 * A split. Send what we currently have.
+			 */
+			XPD_NOTICE(xpd,
+				"%s: xframe is full (%d packets)\n",
+				__func__, packet_count);
+			break;
+		}
+		/* Get data from DAHDI */
+		eoframe = dahdi_hdlc_getbuf(XPD_CHAN(xpd, 2), buf, &len);
+		if (len <= 0) {
+			/*
+			 * Already checked priv->hdlc_pending,
+			 * should never get here.
+			 */
+			if (printk_ratelimit())
+				XPD_ERR(xpd,
+					"%s: hdlc_pending, but nothing to transmit?\n",
+					__func__);
+			FREE_SEND_XFRAME(xpd->xbus, xframe);
+			return -EINVAL;
+		}
+		BUG_ON(len > MULTIBYTE_MAX_LEN);
+		fill_multibyte(xpd, pack, eoframe != 0, buf, len);
+	}
+	return send_dchan_frame(xpd, xframe, eoframe != 0);
 	return ret;
 }
 




More information about the svn-commits mailing list