Page 2 of 4

Re: cross compiling acx100 wifi kernel module

Posted: Tue Aug 03, 2010 7:32 pm
by smartsmurf
jogi10 wrote:here we are again :)
# insmod /dtv/usb/sda1/acx.ko
insmod: cannot insert `/dtv/usb/sda1/acx.ko': Unknown symbol in module (-1): No such file or directory

seems to be a linking problem
Not a linking problem. Rather an issue with not having CONFIG_FW_MODULE set. So there is no firmware loading support from kernel. Even if we compile the module as loadable, we can not modify the files which are required to make it run (e.g. under /etc/... ).

For that reason I added old code for loading firmware in legacy mode. This patch needs to be applied:

Code: Select all

diff -Nur acx.org//acx_func.h acx//acx_func.h
--- acx.org//acx_func.h	2008-02-10 21:06:42.000000000 +0100
+++ acx//acx_func.h	2010-08-03 18:23:32.000000000 +0200
@@ -503,7 +503,11 @@
 
 /***********************************************************************
 */
+#ifdef USE_FW_LOADER_LEGACY
+firmware_image_t *acx_s_read_fw(const char *file, u32 *size);
+#else
 firmware_image_t *acx_s_read_fw(struct device *dev, const char *file, u32 *size);
+#endif
 int acxpci_s_upload_radio(acx_device_t *adev);
 
 
diff -Nur acx.org//acx_struct.h acx//acx_struct.h
--- acx.org//acx_struct.h	2008-02-10 21:06:42.000000000 +0100
+++ acx//acx_struct.h	2010-08-03 17:37:30.000000000 +0200
@@ -1608,6 +1608,17 @@
 #include <linux/firmware.h>	/* request_firmware() */
 #include <linux/pci.h>		/* struct pci_device */
 
+#define USE_FW_LOADER_LEGACY 1
+
+#ifdef USE_FW_LOADER_26
+#include <linux/firmware.h>	/* request_firmware() */
+#include <linux/pci.h>		/* struct pci_device */
+#endif
+
+#ifdef USE_FW_LOADER_LEGACY
+extern char *firmware_dir;
+#endif
+ 
 
 /***********************************************************************
 */
diff -Nur acx.org//common.c acx//common.c
--- acx.org//common.c	2008-02-10 21:06:42.000000000 +0100
+++ acx//common.c	2010-08-03 20:24:14.000000000 +0200
@@ -96,6 +96,10 @@
 MODULE_AUTHOR("ACX100 Open Source Driver development team");
 MODULE_DESCRIPTION("Driver for TI ACX1xx based wireless cards (CardBus/PCI/USB)");
 
+#ifdef USE_FW_LOADER_LEGACY
+module_param(firmware_dir, charp, 0);
+MODULE_PARM_DESC(firmware_dir, "Directory to load acx100 firmware files from");
+#endif
 
 /***********************************************************************
 */
@@ -131,7 +135,9 @@
 	NULL /* needs to remain as last entry */
 };
 
-
+#ifdef USE_FW_LOADER_LEGACY
+char *firmware_dir;
+#endif
 
 /***********************************************************************
 ** Debugging support
@@ -5480,10 +5486,149 @@
 **  0				unable to load file
 **  pointer to firmware		success
 */
+#ifdef USE_FW_LOADER_LEGACY
+static char * const default_firmware_dir = "/dtv/usb/sda1";
+#endif 
+
 firmware_image_t*
+#ifdef USE_FW_LOADER_LEGACY
+acx_s_read_fw(const char *file, u32 *size) 
+#else
 acx_s_read_fw(struct device *dev, const char *file, u32 *size)
+#endif
 {
 	firmware_image_t *res;
+
+#ifdef USE_FW_LOADER_LEGACY
+	mm_segment_t orgfs;
+	unsigned long page;
+	char *buffer;
+	struct file *inf;
+	int retval;
+	u32 offset = 0;
+	char *filename;
+
+	res = NULL;
+
+	orgfs = get_fs(); /* store original fs */
+	set_fs(KERNEL_DS);
+
+	/* Read in whole file then check the size */
+	page = __get_free_page(GFP_KERNEL);
+	if (unlikely(0 == page)) {
+		printk("Unable to allocate memory for firmware loading\n");
+		goto fail;
+	}
+
+	filename = kmalloc(PATH_MAX, GFP_KERNEL);
+	if (unlikely(!filename)) {
+		printk("Unable to allocate memory for firmware loading\n");
+		goto fail;
+	}
+	if (!firmware_dir) {
+		firmware_dir = default_firmware_dir;
+		printk("Attention: no firmware directory specified "
+			"via module parameter firmware_dir, using default "
+			"firmware directory %s\n", firmware_dir);
+	}
+	sprintf(filename,"%s/%s", firmware_dir, file);
+	printk("Reading firmware image '%s'\n", filename);
+
+	buffer = (char*)page;
+	
+	/* Note that file must be given as absolute path:
+	 * a relative path works on first loading,
+	 * but any subsequent firmware loading during card
+	 * eject/insert will fail, most likely since the first
+	 * module loading happens in user space (and thus
+	 * filp_open can figure out the absolute path from a
+	 * relative path) whereas the card reinsert processing
+	 * probably happens in kernel space where you don't have
+	 * a current directory to be able to figure out an
+	 * absolute path from a relative path... */
+	inf = filp_open(filename, O_RDONLY, 0);
+	kfree(filename);
+	if (OK != IS_ERR(inf)) {
+		const char *err;
+
+		switch(-PTR_ERR(inf)) {
+			case 2: err = "file not found - make sure this EXACT filename is in eXaCtLy this directory!";
+				break;
+			default:
+				err = "unknown error";
+				break;
+		}
+		printk("ERROR %ld trying to open firmware image file '%s': %s\n", -PTR_ERR(inf), file, err);
+		goto fail;
+	}
+
+	if (unlikely((NULL == inf->f_op) || (NULL == inf->f_op->read))) {
+		printk("ERROR: %s does not have a read method\n", file);
+		goto fail_close;
+	}
+
+	offset = 0;
+	do {
+		retval = inf->f_op->read(inf, buffer, PAGE_SIZE, &inf->f_pos);
+
+		if (unlikely(0 > retval)) {
+			printk("ERROR %d reading firmware image file '%s'.\n", -retval, file);
+			if (NULL != res)
+				vfree(res);
+			res = NULL;
+		} else if (0 == retval) {
+			if (0 == offset) {
+				printk("ERROR: firmware image file '%s' is empty.\n", file);
+			}
+		} else if (0 < retval) {
+			/* allocate result buffer here if needed,
+			 * since we don't want to waste resources/time
+			 * (in case file opening/reading fails)
+			 * by doing allocation in front of the loop instead. */
+			if (NULL == res) {
+				*size = 8 + le32_to_cpu(*(u32 *)(4 + buffer));
+
+				res = vmalloc(*size);
+				if (NULL == res) {
+					printk("ERROR: Unable to allocate %u bytes for firmware module loading.\n", *size);
+					goto fail_close;
+				}
+				printk("Allocated %u bytes for firmware module loading.\n", *size);
+			}
+			if ((unlikely(offset + retval > *size)))
+			{
+				printk("ERROR: allocation was less than firmware image size!\n");
+				goto fail_close;
+			}
+			memcpy((u8*)res + offset, buffer, retval);
+			offset += retval;
+		}
+	} while (0 < retval);
+
+fail_close:
+	retval = filp_close(inf, NULL);
+
+	if (unlikely(retval)) {
+		printk("ERROR %d closing %s\n", -retval, file);
+	}
+
+	if (unlikely((NULL != res) && (offset != le32_to_cpu(res->size) + 8))) {
+		printk("Firmware is reporting a different size (0x%08x; 0x%08x was read)\n", le32_to_cpu(res->size) + 8, offset);
+		vfree(res);
+		res = NULL;
+	}
+
+fail:
+	if (page)
+		free_page(page);
+	set_fs(orgfs);
+
+/* ret: */
+	/* checksum will be verified in write_fw, so don't bother here */
+
+	return res;
+
+#else
 	const struct firmware *fw_entry;
 
 	res = NULL;
@@ -5515,6 +5660,7 @@
 
 	/* checksum will be verified in write_fw, so don't bother here */
 	return res;
+#endif
 }
 
 
diff -Nur acx.org//pci.c acx//pci.c
--- acx.org//pci.c	2008-02-10 21:06:42.000000000 +0100
+++ acx//pci.c	2010-08-03 20:05:44.000000000 +0200
@@ -630,11 +630,19 @@
 	snprintf(filename, sizeof(filename), "tiacx1%02dc%02X",
 		IS_ACX111(adev)*11, adev->radio_type);
 
+#ifdef USE_FW_LOADER_LEGACY
+	fw_image = acx_s_read_fw(filename, &file_size);
+#else
 	fw_image = acx_s_read_fw(adev->bus_dev, filename, &file_size);
+#endif
 	if (!fw_image) {
 		adev->need_radio_fw = 1;
 		filename[sizeof("tiacx1NN")-1] = '\0';
+#ifdef USE_FW_LOADER_LEGACY
+		fw_image = acx_s_read_fw(filename, &file_size);
+#else
 		fw_image = acx_s_read_fw(adev->bus_dev, filename, &file_size);
+#endif
 		if (!fw_image) {
 			FN_EXIT1(NOT_OK);
 			return NOT_OK;
@@ -692,7 +700,11 @@
 	snprintf(filename, sizeof(filename), "tiacx1%02dr%02X",
 		IS_ACX111(adev)*11,
 		adev->radio_type);
+#ifdef USE_FW_LOADER_LEGACY
+	radio_image = acx_s_read_fw(filename, &size);
+#else
 	radio_image = acx_s_read_fw(adev->bus_dev, filename, &size);
+#endif
 	if (!radio_image) {
 		printk("acx: can't load radio module '%s'\n", filename);
 		goto fail;
diff -Nur acx.org//usb.c acx//usb.c
--- acx.org//usb.c	2008-02-10 21:06:42.000000000 +0100
+++ acx//usb.c	2010-08-03 17:53:48.000000000 +0200
@@ -538,7 +538,11 @@
 	snprintf(filename, sizeof(filename), "tiacx1%02dusbc%02X",
 				is_tnetw1450 * 11, *radio_type);
 
+#ifdef USE_FW_LOADER_LEGACY
+	fw_image = acx_s_read_fw(filename, &file_size);
+#else
 	fw_image = acx_s_read_fw(&usbdev->dev, filename, &file_size);
+#endif
 	if (!fw_image) {
 		result = -EIO;
 		goto end; 
I compiled the driver and updated my initial post in this thread with new acx.ko. Default firmware directory is set to "/dtv/usb/sda1".

Re: cross compiling acx100 wifi kernel module

Posted: Tue Aug 03, 2010 9:41 pm
by smartsmurf
The toolchain is fine for your device.

Re: cross compiling acx100 wifi kernel module

Posted: Wed Aug 04, 2010 9:26 pm
by smartsmurf
jogi10 wrote: In dmesg log were several entries of driver complaining about too large packet size, I guess due this protocol violation, the driver couldn't find any AP id. I'll add logfiles tomorrow ... what a pity if this is the end
I assume this comes from this piece of code:

Code: Select all

	if (unlikely(size > sizeof(rxbuffer_t)))
		printk("acx_usb: rx too large: %d, please report\n", size);

Re: cross compiling acx100 wifi kernel module

Posted: Thu Aug 05, 2010 7:59 am
by smartsmurf
OK, in this case I suggest to increase WLAN_DATA_MAXLEN from 2304 (802.11 standard) to 4000 bytes. Some routers might present larger packets.

Code: Select all

#define WLAN_DATA_MAXLEN		4000
Please find attached the compiled experimental modification to that driver.

Good luck,
SM

Re: cross compiling acx100 wifi kernel module

Posted: Thu Aug 05, 2010 11:01 am
by smartsmurf
In fact, there is more problems with your device:

Code: Select all

<4>acx: issue_cmd(): USB read error -75
<4>acx: issue_cmd(cmd:ACX1xx_CMD_INTERROGATE) FAILED
...
<4>wlan%d: interrogate(type:ACX1xx_IE_MEMORY_CONFIG_OPTIONS) FAILED
...
<4>don't know how to get sensitivity for radio type 0x1B
<4>got sensitivity value 0
...
<4>acx: === chipset TNETW1450, radio type 0x1B (An unknown radio used by TNETW1450 USB adapters), form factor 0x00 (unspecified), EEPROM version 0x05: uploaded firmware 'Rev 2.4.0.70' ===

It looks like your WLAN device is not supported by the driver. Not surprisingly since the sources are from 2008...