patch-2.3.99-pre3 linux/drivers/atm/atmtcp.c

Next file: linux/drivers/atm/eni.c
Previous file: linux/drivers/atm/atmdev_init.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.99-pre2/linux/drivers/atm/atmtcp.c linux/drivers/atm/atmtcp.c
@@ -7,7 +7,9 @@
 #include <linux/wait.h>
 #include <linux/atmdev.h>
 #include <linux/atm_tcp.h>
+#include <linux/bitops.h>
 #include <asm/uaccess.h>
+#include <asm/atomic.h>
 
 
 extern int atm_init_aal5(struct atm_vcc *vcc); /* "raw" AAL5 transport */
@@ -36,12 +38,14 @@
 
 
 static int atmtcp_send_control(struct atm_vcc *vcc,int type,
-    const struct atmtcp_control *msg,unsigned short flag)
+    const struct atmtcp_control *msg,int flag)
 {
+	DECLARE_WAITQUEUE(wait,current);
 	struct atm_vcc *out_vcc;
 	struct sk_buff *skb;
 	struct atmtcp_control *new_msg;
-	unsigned short old_flags;
+	int old_test;
+	int error = 0;
 
 	out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL;
 	if (!out_vcc) return -EUNATCH;
@@ -60,16 +64,21 @@
 	new_msg->type = type;
 	memset(&new_msg->vcc,0,sizeof(atm_kptr_t));
 	*(struct atm_vcc **) &new_msg->vcc = vcc;
-	old_flags = vcc->flags;
+	old_test = test_bit(flag,&vcc->flags);
 	out_vcc->push(out_vcc,skb);
-	while (!((vcc->flags ^ old_flags) & flag)) {
+	add_wait_queue(&vcc->sleep,&wait);
+	while (test_bit(flag,&vcc->flags) == old_test) {
 		mb();
 		out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL;
-		if (!out_vcc) return -EUNATCH;
-		sleep_on(&vcc->sleep);
-		
+		if (!out_vcc) {
+			error = -EUNATCH;
+			break;
+		}
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule();
 	}
-	return 0;
+	remove_wait_queue(&vcc->sleep,&wait);
+	return error;
 }
 
 
@@ -83,10 +92,10 @@
 	vcc->reply = msg->result;
 	switch (msg->type) {
 	    case ATMTCP_CTRL_OPEN:
-		vcc->flags ^= ATM_VF_READY;
+		change_bit(ATM_VF_READY,&vcc->flags);
 		break;
 	    case ATMTCP_CTRL_CLOSE:
-		vcc->flags ^= ATM_VF_ADDR;
+		change_bit(ATM_VF_ADDR,&vcc->flags);
 		break;
 	    default:
 		printk(KERN_ERR "atmtcp_recv_control: unknown type %d\n",
@@ -120,8 +129,8 @@
 	if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) return 0;
 	msg.type = ATMTCP_CTRL_OPEN;
 	msg.qos = vcc->qos;
-	vcc->flags |= ATM_VF_ADDR;
-	vcc->flags &= ~ATM_VF_READY; /* just in case ... */
+	set_bit(ATM_VF_ADDR,&vcc->flags);
+	clear_bit(ATM_VF_READY,&vcc->flags); /* just in case ... */
 	error = atmtcp_send_control(vcc,ATMTCP_CTRL_OPEN,&msg,ATM_VF_READY);
 	if (error) return error;
 	return vcc->reply;
@@ -136,7 +145,7 @@
 	msg.addr.sap_family = AF_ATMPVC;
 	msg.addr.sap_addr.vpi = vcc->vpi;
 	msg.addr.sap_addr.vci = vcc->vci;
-	vcc->flags &= ~ATM_VF_READY;
+	clear_bit(ATM_VF_READY,&vcc->flags);
 	(void) atmtcp_send_control(vcc,ATMTCP_CTRL_CLOSE,&msg,ATM_VF_ADDR);
 }
 
@@ -168,13 +177,18 @@
 	struct atmtcp_hdr *hdr;
 	int size;
 
+	if (vcc->qos.txtp.traffic_class == ATM_NONE) {
+		if (vcc->pop) vcc->pop(vcc,skb);
+		else dev_kfree_skb(skb);
+		return -EINVAL;
+	}
 	dev_data = PRIV(vcc->dev);
 	if (dev_data) out_vcc = dev_data->vcc;
 	if (!dev_data || !out_vcc) {
 		if (vcc->pop) vcc->pop(vcc,skb);
 		else dev_kfree_skb(skb);
 		if (dev_data) return 0;
-		vcc->stats->tx_err++;
+		atomic_inc(&vcc->stats->tx_err);
 		return -ENOLINK;
 	}
 	size = skb->len+sizeof(struct atmtcp_hdr);
@@ -182,7 +196,7 @@
 	if (!new_skb) {
 		if (vcc->pop) vcc->pop(vcc,skb);
 		else dev_kfree_skb(skb);
-		vcc->stats->tx_err++;
+		atomic_inc(&vcc->stats->tx_err);
 		return -ENOBUFS;
 	}
 	hdr = (void *) skb_put(new_skb,sizeof(struct atmtcp_hdr));
@@ -193,8 +207,8 @@
 	if (vcc->pop) vcc->pop(vcc,skb);
 	else dev_kfree_skb(skb);
 	out_vcc->push(out_vcc,new_skb);
-	vcc->stats->tx++;
-	out_vcc->stats->rx++;
+	atomic_inc(&vcc->stats->tx);
+	atomic_inc(&out_vcc->stats->rx);
 	return 0;
 }
 
@@ -251,7 +265,7 @@
 		    out_vcc->qos.rxtp.traffic_class != ATM_NONE)
 			break;
 	if (!out_vcc) {
-		vcc->stats->tx_err++;
+		atomic_inc(&vcc->stats->tx_err);
 		goto done;
 	}
 	skb_pull(skb,sizeof(struct atmtcp_hdr));
@@ -263,8 +277,8 @@
 	new_skb->stamp = xtime;
 	memcpy(skb_put(new_skb,skb->len),skb->data,skb->len);
 	out_vcc->push(out_vcc,new_skb);
-	vcc->stats->tx++;
-	out_vcc->stats->rx++;
+	atomic_inc(&vcc->stats->tx);
+	atomic_inc(&out_vcc->stats->rx);
 done:
 	if (vcc->pop) vcc->pop(vcc,skb);
 	else dev_kfree_skb(skb);
@@ -305,7 +319,7 @@
 	999,		/* dummy device number */
 	NULL,NULL,	/* pretend not to have any VCCs */
 	NULL,NULL,	/* no data */
-	0,		/* no flags */
+	{ 0 },		/* no flags */
 	NULL,		/* no local address */
 	{ 0 }		/* no ESI, no statistics */
 };
@@ -318,7 +332,7 @@
 
 	dev_data = kmalloc(sizeof(*dev_data),GFP_KERNEL);
 	if (!dev_data) return -ENOMEM;
-	dev = atm_dev_register(DEV_LABEL,&atmtcp_v_dev_ops,itf,0);
+	dev = atm_dev_register(DEV_LABEL,&atmtcp_v_dev_ops,itf,NULL);
 	if (!dev) {
 		kfree(dev_data);
 		return itf == -1 ? -ENOMEM : -EBUSY;
@@ -352,7 +366,8 @@
 	}
 	PRIV(dev)->vcc = vcc;
 	bind_vcc(vcc,&atmtcp_control_dev);
-	vcc->flags |= ATM_VF_READY | ATM_VF_META;
+	set_bit(ATM_VF_META,&vcc->flags);
+	set_bit(ATM_VF_READY,&vcc->flags);
 	vcc->dev_data = dev;
 	(void) atm_init_aal5(vcc); /* @@@ losing AAL in transit ... */
 	vcc->stats = &atmtcp_control_dev.stats.aal5;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)