Il giorno mer, 02/08/2006 alle 10.51 +0200, Dario Lesca ha scritto:
produced this structure (see attach):
Makefile:
obj-m += usbatm.o
obj-m += cxacru.o
PWD := $(shell pwd)
MDIR := /lib/modules/$(shell uname -r)
KDIR := $(MDIR)/build
SUDO := sudo -p 'Sudo Password: '
default:
@echo "make {patch|build|install|uninstall|clean|cleanall}"
#Patch
patch: usbatm.c.orig usbatm.h.orig
patch < usbatm-oam-support.patch
usbatm.c.orig:
test -f usbatm.c.orig && exit 1
cp -a usbatm.c usbatm.c.orig
usbatm.h.orig:
test -f usbatm.h.orig && exit 1
cp -a usbatm.h usbatm.h.orig
#Build
build: usbatm.ko cxacru.ko
usbatm.ko: usbatm.c
$(MAKE) -C $(KDIR) M=$(PWD) modules
cxacru.ko: cxacru.c
$(MAKE) -C $(KDIR) M=$(PWD) modules
#Install
install: usbatm.ko cxacru.ko uninstall
$(SUDO) sh -x -c '/sbin/modprobe -rv cxacru;\
/sbin/modprobe -rv usbatm;\
cp -a usbatm.ko $(MDIR)/updates/.;\
cp -a cxacru.ko $(MDIR)/updates/.;\
/sbin/depmod -a;\
/sbin/modprobe -v cxacru;\
/sbin/modprobe -v usbatm'
uninstall:
$(SUDO) sh -x -c '/sbin/modprobe -rv cxacru;\
/sbin/modprobe -rv usbatm;\
/sbin/modprobe -rv cxacru;\
rm -f $(MDIR)/updates/usbatm.ko;\
rm -f $(MDIR)/updates/cxacru.ko;\
/sbin/depmod -a;\
/sbin/modprobe -v cxacru;\
/sbin/modprobe -v usbatm'
#Clear files
clear: clean
clean:
rm -fr \
usbatm.ko usbatm.mod.c usbatm.mod.o usbatm.o \
.usbatm.ko.cmd .usbatm.mod.o.cmd .usbatm.o.cmd \
cxacru.ko cxacru.mod.c cxacru.mod.o cxacru.o \
.cxacru.ko.cmd .cxacru.mod.o.cmd .cxacru.o.cmd \
Modules.symvers .tmp_versions
cleanall: clean uninstall
usbatm-oam-support.patch:
diff -u atm.orig/usbatm.c atm/usbatm.c
--- atm.orig/usbatm.c 2006-06-18 03:49:35.000000000 +0200
+++ atm/usbatm.c 2006-07-25 12:07:28.000000000 +0200
@@ -92,18 +92,18 @@
#endif
#define DRIVER_AUTHOR "Johan Verrept, Duncan Sands
<duncan.sands(a)free.fr>"
-#define DRIVER_VERSION "1.10"
+#define DRIVER_VERSION "1.10-OAM"
#define DRIVER_DESC "Generic USB ATM/DSL I/O, version " DRIVER_VERSION
static const char usbatm_driver_name[] = "usbatm";
#define UDSL_MAX_RCV_URBS 16
#define UDSL_MAX_SND_URBS 16
-#define UDSL_MAX_BUF_SIZE 65536
+#define UDSL_MAX_BUF_SIZE 64 * 1024 /* bytes */
#define UDSL_DEFAULT_RCV_URBS 4
#define UDSL_DEFAULT_SND_URBS 4
-#define UDSL_DEFAULT_RCV_BUF_SIZE 3392 /* 64 * ATM_CELL_SIZE */
-#define UDSL_DEFAULT_SND_BUF_SIZE 3392 /* 64 * ATM_CELL_SIZE */
+#define UDSL_DEFAULT_RCV_BUF_SIZE 64 * ATM_CELL_SIZE /* bytes */
+#define UDSL_DEFAULT_SND_BUF_SIZE 64 * ATM_CELL_SIZE /* bytes */
#define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD)
@@ -135,7 +135,7 @@
module_param(snd_buf_bytes, uint, S_IRUGO);
MODULE_PARM_DESC(snd_buf_bytes,
"Size of the buffers used for transmission, in bytes (range:
1-"
- __MODULE_STRING(UDSL_MAX_BUF_SIZE) ", default: "
+ __MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: "
__MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")");
@@ -183,7 +183,6 @@
.owner = THIS_MODULE,
};
-
/***********
** misc **
***********/
@@ -202,12 +201,37 @@
dev_kfree_skb_any(skb);
}
+static u16 crc10_table[256] = {
+ 0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff, 0x301, 0x132, 0x154,
0x367, 0x198, 0x3ab, 0x3cd, 0x1fe,
+ 0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce, 0x330, 0x103, 0x165,
0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf,
+ 0x062, 0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d, 0x363, 0x150, 0x136,
0x305, 0x1fa, 0x3c9, 0x3af, 0x19c,
+ 0x053, 0x260, 0x206, 0x035, 0x2ca, 0x0f9, 0x09f, 0x2ac, 0x352, 0x161, 0x107,
0x334, 0x1cb, 0x3f8, 0x39e, 0x1ad,
+ 0x0c4, 0x2f7, 0x291, 0x0a2, 0x25d, 0x06e, 0x008, 0x23b, 0x3c5, 0x1f6, 0x190,
0x3a3, 0x15c, 0x36f, 0x309, 0x13a,
+ 0x0f5, 0x2c6, 0x2a0, 0x093, 0x26c, 0x05f, 0x039, 0x20a, 0x3f4, 0x1c7, 0x1a1,
0x392, 0x16d, 0x35e, 0x338, 0x10b,
+ 0x0a6, 0x295, 0x2f3, 0x0c0, 0x23f, 0x00c, 0x06a, 0x259, 0x3a7, 0x194, 0x1f2,
0x3c1, 0x13e, 0x30d, 0x36b, 0x158,
+ 0x097, 0x2a4, 0x2c2, 0x0f1, 0x20e, 0x03d, 0x05b, 0x268, 0x396, 0x1a5, 0x1c3,
0x3f0, 0x10f, 0x33c, 0x35a, 0x169,
+ 0x188, 0x3bb, 0x3dd, 0x1ee, 0x311, 0x122, 0x144, 0x377, 0x289, 0x0ba, 0x0dc,
0x2ef, 0x010, 0x223, 0x245, 0x076,
+ 0x1b9, 0x38a, 0x3ec, 0x1df, 0x320, 0x113, 0x175, 0x346, 0x2b8, 0x08b, 0x0ed,
0x2de, 0x021, 0x212, 0x274, 0x047,
+ 0x1ea, 0x3d9, 0x3bf, 0x18c, 0x373, 0x140, 0x126, 0x315, 0x2eb, 0x0d8, 0x0be,
0x28d, 0x072, 0x241, 0x227, 0x014,
+ 0x1db, 0x3e8, 0x38e, 0x1bd, 0x342, 0x171, 0x117, 0x324, 0x2da, 0x0e9, 0x08f,
0x2bc, 0x043, 0x270, 0x216, 0x025,
+ 0x14c, 0x37f, 0x319, 0x12a, 0x3d5, 0x1e6, 0x180, 0x3b3, 0x24d, 0x07e, 0x018,
0x22b, 0x0d4, 0x2e7, 0x281, 0x0b2,
+ 0x17d, 0x34e, 0x328, 0x11b, 0x3e4, 0x1d7, 0x1b1, 0x382, 0x27c, 0x04f, 0x029,
0x21a, 0x0e5, 0x2d6, 0x2b0, 0x083,
+ 0x12e, 0x31d, 0x37b, 0x148, 0x3b7, 0x184, 0x1e2, 0x3d1, 0x22f, 0x01c, 0x07a,
0x249, 0x0b6, 0x285, 0x2e3, 0x0d0,
+ 0x11f, 0x32c, 0x34a, 0x179, 0x386, 0x1b5, 0x1d3, 0x3e0, 0x21e, 0x02d, 0x04b,
0x278, 0x087, 0x2b4, 0x2d2, 0x0e1,
+};
+
+static u16 inline crc10(u16 init, u8 *data, int len)
+{
+ while (len--)
+ init = ((init << 8) & 0x3ff) ^ crc10_table[(init >> 2)
& 0xff] ^ *data++;
+ return init;
+}
/***********
** urbs **
************/
-static struct urb *usbatm_pop_urb(struct usbatm_channel *channel)
+static inline struct urb *usbatm_pop_urb(struct usbatm_channel *channel)
{
struct urb *urb;
@@ -224,7 +248,7 @@
return urb;
}
-static int usbatm_submit_urb(struct urb *urb)
+static inline int usbatm_submit_urb(struct urb *urb)
{
struct usbatm_channel *channel = urb->context;
int ret;
@@ -283,6 +307,42 @@
tasklet_schedule(&channel->tasklet);
}
+/* OAM loopback reply (fire-and-forget) */
+static int usbatm_oam_reply(struct usbatm_data *instance, u8 *source)
+{
+ struct urb *urb;
+ u16 crc;
+ u8 *buffer;
+
+ if (source[ATM_CELL_HEADER] != 0x18 || source[ATM_CELL_HEADER + 1] != 0x01) {
+ atm_dbg(instance, "%s: unexpected OAM type/function %x direction
%x!\n",
+ __func__, source[ATM_CELL_HEADER], source[ATM_CELL_HEADER + 1]);
+ return -EPROTO;
+ }
+
+ if (crc10(0, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD)) {
+ atm_dbg(instance, "%s: OAM CRC10 error!\n", __func__);
+ return -EIO;
+ }
+
+ urb = usbatm_pop_urb(&instance->tx_channel);
+ if (!urb)
+ return -ENOMEM;
+
+ buffer = urb->transfer_buffer;
+ memcpy(buffer, source, ATM_CELL_SIZE);
+
+ buffer[ATM_CELL_HEADER + 1] = 0; /* update the direction field */
+
+ memset(buffer + ATM_CELL_SIZE - 2, 0, 2);
+
+ crc = crc10(0, buffer + ATM_CELL_HEADER, ATM_CELL_PAYLOAD);
+ buffer[ATM_CELL_SIZE - 2] = (crc >> 8) & 0x3;
+ buffer[ATM_CELL_SIZE - 1] = crc & 0xff;
+
+ urb->transfer_buffer_length = instance->tx_channel.stride;
+ return usbatm_submit_urb(urb);
+}
/*************
** decode **
@@ -324,12 +384,24 @@
vcc = instance->cached_vcc->vcc;
+// /* OAM F5 end-to-end */
+// if (pti == ATM_PTI_E2EF5) {
+// if (printk_ratelimit())
+// atm_warn(instance, "%s: OAM not supported (vpi %d, vci
%d)!\n",
+// __func__, vpi, vci);
+// atomic_inc(&vcc->stats->rx_err);
+// return;
+// }
+
/* OAM F5 end-to-end */
if (pti == ATM_PTI_E2EF5) {
if (printk_ratelimit())
- atm_warn(instance, "%s: OAM not supported (vpi %d, vci
%d)!\n",
+ atm_warn(instance, "%s: Trying to support OAM (vpi %d, vci
%d)!\n",
__func__, vpi, vci);
- atomic_inc(&vcc->stats->rx_err);
+ if (usbatm_oam_reply(instance, source)) {
+ atm_dbg(instance, "%s: OAM reply failed (vpi %d, vci
%d)!\n", __func__, vpi, vci);
+ atomic_inc(&vcc->stats->rx_err);
+ }
return;
}
@@ -823,7 +895,7 @@
return -EINVAL;
}
- mutex_lock(&instance->serialize); /* vs self, usbatm_atm_close,
usbatm_usb_disconnect */+ down(&instance->serialize); /* vs self,
usbatm_atm_close, usbatm_usb_disconnect */
if (instance->disconnected) {
atm_dbg(instance, "%s: disconnected!\n", __func__);
@@ -837,7 +909,7 @@
goto fail;
}
- if (!(new = kzalloc(sizeof(struct usbatm_vcc_data), GFP_KERNEL))) {
+ if (!(new = kmalloc(sizeof(struct usbatm_vcc_data), GFP_KERNEL))) {
atm_err(instance, "%s: no memory for vcc_data!\n", __func__);
ret = -ENOMEM;
goto fail;
@@ -867,7 +939,7 @@
set_bit(ATM_VF_PARTIAL, &vcc->flags);
set_bit(ATM_VF_READY, &vcc->flags);
- mutex_unlock(&instance->serialize);
+ up(&instance->serialize);
atm_dbg(instance, "%s: allocated vcc data 0x%p\n", __func__, new);
@@ -875,7 +947,7 @@
fail:
kfree(new);
- mutex_unlock(&instance->serialize);
+ up(&instance->serialize);
return ret;
}
@@ -896,7 +968,7 @@
usbatm_cancel_send(instance, vcc);
- mutex_lock(&instance->serialize); /* vs self, usbatm_atm_open,
usbatm_usb_disconnect */
+ down(&instance->serialize); /* vs self, usbatm_atm_open,
usbatm_usb_disconnect */
tasklet_disable(&instance->rx_channel.tasklet);
if (instance->cached_vcc == vcc_data) {
@@ -919,7 +991,7 @@
clear_bit(ATM_VF_PARTIAL, &vcc->flags);
clear_bit(ATM_VF_ADDR, &vcc->flags);
- mutex_unlock(&instance->serialize);
+ up(&instance->serialize);
atm_dbg(instance, "%s successful\n", __func__);
}
@@ -1009,9 +1081,9 @@
if (!ret)
ret = usbatm_atm_init(instance);
- mutex_lock(&instance->serialize);
+ down(&instance->serialize);
instance->thread_pid = -1;
- mutex_unlock(&instance->serialize);
+ up(&instance->serialize);
complete_and_exit(&instance->thread_exited, ret);
}
@@ -1025,9 +1097,9 @@
return ret;
}
- mutex_lock(&instance->serialize);
+ down(&instance->serialize);
instance->thread_pid = ret;
- mutex_unlock(&instance->serialize);
+ up(&instance->serialize);
wait_for_completion(&instance->thread_started);
@@ -1066,7 +1138,7 @@
intf->altsetting->desc.bInterfaceNumber);
/* instance init */
- instance = kzalloc(sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs +
num_snd_urbs), GFP_KERNEL);
+ instance = kmalloc(sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs +
num_snd_urbs), GFP_KERNEL);
if (!instance) {
dev_err(dev, "%s: no memory for instance data!\n", __func__);
return -ENOMEM;
@@ -1110,7 +1182,7 @@
/* private fields */
kref_init(&instance->refcount); /* dropped in
usbatm_usb_disconnect */
- mutex_init(&instance->serialize);
+ init_MUTEX(&instance->serialize);
instance->thread_pid = -1;
init_completion(&instance->thread_started);
@@ -1186,7 +1258,7 @@
instance->urbs[i] = urb;
/* zero the tx padding to avoid leaking information */
- buffer = kzalloc(channel->buf_size, GFP_KERNEL);
+ buffer = kmalloc(channel->buf_size, GFP_KERNEL);
if (!buffer) {
dev_err(dev, "%s: no memory for buffer %d!\n",
__func__, i);
error = -ENOMEM;
@@ -1273,18 +1345,18 @@
usb_set_intfdata(intf, NULL);
- mutex_lock(&instance->serialize);
+ down(&instance->serialize);
instance->disconnected = 1;
if (instance->thread_pid >= 0)
kill_proc(instance->thread_pid, SIGTERM, 1);
- mutex_unlock(&instance->serialize);
+ up(&instance->serialize);
wait_for_completion(&instance->thread_exited);
- mutex_lock(&instance->serialize);
+ down(&instance->serialize);
list_for_each_entry(vcc_data, &instance->vcc_list, list)
vcc_release_async(vcc_data->vcc, -EPIPE);
- mutex_unlock(&instance->serialize);
+ up(&instance->serialize);
tasklet_disable(&instance->rx_channel.tasklet);
tasklet_disable(&instance->tx_channel.tasklet);
diff -u atm.orig/usbatm.h atm/usbatm.h
--- atm.orig/usbatm.h 2006-06-18 03:49:35.000000000 +0200
+++ atm/usbatm.h 2006-07-25 12:11:53.000000000 +0200
@@ -34,7 +34,6 @@
#include <linux/list.h>
#include <linux/stringify.h>
#include <linux/usb.h>
-#include <linux/mutex.h>
/*
#define VERBOSE_DEBUG
@@ -172,7 +171,7 @@
********************************/
struct kref refcount;
- struct mutex serialize;
+ struct semaphore serialize;
int disconnected;
/* heavy init */
--
Dario Lesca <d.lesca(a)solinos.it>