[Bluetooth] Allow disabling of credit based flow control

This patch adds the module parameter disable_cfc which can be used to
disable the credit based flow control. The credit based flow control
was introduced with the Bluetooth 1.1 specification and devices can
negotiate its support, but for testing purpose it is helpful to allow
disabling of it.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 6de33fe..fe18dc2 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -52,8 +52,9 @@
 #define BT_DBG(D...)
 #endif
 
-#define VERSION "1.7"
+#define VERSION "1.8"
 
+static int disable_cfc = 0;
 static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU;
 
 static struct task_struct *rfcomm_thread;
@@ -533,7 +534,7 @@
 	s->sock  = sock;
 
 	s->mtu = RFCOMM_DEFAULT_MTU;
-	s->cfc = RFCOMM_CFC_UNKNOWN;
+	s->cfc = disable_cfc ? RFCOMM_CFC_DISABLED : RFCOMM_CFC_UNKNOWN;
 
 	/* Do not increment module usage count for listening sessions.
 	 * Otherwise we won't be able to unload the module. */
@@ -1222,14 +1223,18 @@
 	BT_DBG("dlc %p state %ld dlci %d mtu %d fc 0x%x credits %d", 
 			d, d->state, d->dlci, pn->mtu, pn->flow_ctrl, pn->credits);
 
-	if (pn->flow_ctrl == 0xf0 || pn->flow_ctrl == 0xe0) {
-		d->cfc = s->cfc = RFCOMM_CFC_ENABLED;
+	if ((pn->flow_ctrl == 0xf0 && s->cfc != RFCOMM_CFC_DISABLED) ||
+						pn->flow_ctrl == 0xe0) {
+		d->cfc = RFCOMM_CFC_ENABLED;
 		d->tx_credits = pn->credits;
 	} else {
-		d->cfc = s->cfc = RFCOMM_CFC_DISABLED;
+		d->cfc = RFCOMM_CFC_DISABLED;
 		set_bit(RFCOMM_TX_THROTTLED, &d->flags);
 	}
 
+	if (s->cfc == RFCOMM_CFC_UNKNOWN)
+		s->cfc = d->cfc;
+
 	d->priority = pn->priority;
 
 	d->mtu = s->mtu = btohs(pn->mtu);
@@ -2073,6 +2078,9 @@
 module_init(rfcomm_init);
 module_exit(rfcomm_exit);
 
+module_param(disable_cfc, bool, 0644);
+MODULE_PARM_DESC(disable_cfc, "Disable credit based flow control");
+
 module_param(l2cap_mtu, uint, 0644);
 MODULE_PARM_DESC(l2cap_mtu, "Default MTU for the L2CAP connection");