From: Ziggy471 Date: Thu, 20 Jan 2011 20:44:37 +0000 (-0500) Subject: Update WiMax drivers X-Git-Url: https://ziggy471.com/git/gitweb.cgi?p=ziggy471-frankenstein-kernel.git;a=commitdiff;h=50c28184cb661763761b2d768a7ad67eee4aa2f1 Update WiMax drivers --- --- a/drivers/net/wimax/Makefile +++ b/drivers/net/wimax/Makefile @@ -1,6 +1,8 @@ obj-$(CONFIG_WIMAX_I2400M) += i2400m/ obj-$(CONFIG_WIMAX_SQN) += SQN/ +obj-$(CONFIG_WIMAX_SQN) += wimaxdbg/ +obj-$(CONFIG_WIMAX_SQN) += wimaxuart/ # (from Sam Ravnborg) force kbuild to create built-in.o obj- := dummy.o --- a/drivers/net/wimax/SQN/Makefile +++ b/drivers/net/wimax/SQN/Makefile @@ -77,7 +77,7 @@ SQN_USB := obj-$(SQN_SDIO) += sequans_sdio.o obj-$(SQN_USB) += sequans_usb.o -sequans_sdio-objs := sdio.o sdio-driver.o sdio-fw.o sdio-pm.o thp.o +sequans_sdio-objs := sdio.o sdio-driver.o sdio-fw.o sdio-pm.o thp.o sdio_netlink.o msg.o sequans_usb-objs := usb-driver.o thp.o @@ -96,21 +96,6 @@ sequans_usb-objs := usb-driver.o thp.o EXTRA_CFLAGS += -D$(SQN_TARGET) -Wno-unused-function -Wno-unused-label \ -Wno-unused-variable - -### For TI kernel we need the following lines -### For other kernels we should comment them - -#EXTRA_CFLAGS += -DTI_KERNEL -#sequans_sdio-objs += sdio-ti.o - -### end of TI kernel specific options - - -### For ANDROID kernel we need the following lines -### For other kernels we should comment them - EXTRA_CFLAGS += -DANDROID_KERNEL -### end of HTC kernel specific options - endif --- /dev/null +++ b/drivers/net/wimax/SQN/msg.c @@ -0,0 +1,944 @@ +#include "msg.h" + +#define LARGESTRING 1024 + +#define SPERW (7 * 24 * 3600) +#define SPERD (24 * 3600) +#define SPERH (3600) +#define SPERM (60) + +#define SQN_PRT_MODULE_NAME "wimax_prt" + +void printTime32(u_char *data); + +void sqn_pr_info_dump(char *prefix, unsigned char *data, unsigned int len) { + unsigned int i = 0, pos = 0, temp = 0; + unsigned int width = 16; + unsigned int len_ = (unsigned int)(len); + + char buf[LARGESTRING]; + + int opCode = 0; + int bHandle = 0; + + // sequans_xxx: RX PDU: 0000 ff ff ff ff ff ff 00 1e 90 21 0b d4 08 00 45 00 + // while (i < len_) { // Andrew 0903 + if (i < len_) { + if (i % width == 0) + { + if (len_ >= 40 && !bHandle) { // ARP [ + if ( (((unsigned char *)(data))[i+12] == 0x08) && + (((unsigned char *)(data))[i+13] == 0x06) ) { + + bHandle = 1; + + // Opcode + opCode = 0; + if ( (((unsigned char *)(data))[i+20] == 0x00) && + (((unsigned char *)(data))[i+21] == 0x01) ) { + printk(KERN_INFO "%s: [ARP request] - ", SQN_PRT_MODULE_NAME); + opCode = 1; + } + else if ( (((unsigned char *)(data))[i+20] == 0x00) && + (((unsigned char *)(data))[i+21] == 0x02) ) { + printk(KERN_INFO "%s: [ARP reply] - ", SQN_PRT_MODULE_NAME); + opCode = 2; + } + + if (opCode == 1) { // request + printk("Who has "); + for (pos=38; pos<42; pos++) { + if (pos<41) + printk("%d.", ((unsigned char *)(data))[pos]); + else + printk("%d Tell ", ((unsigned char *)(data))[pos]); + } + for (pos=28; pos<32; pos++) { + if (pos<31) + printk("%d.", ((unsigned char *)(data))[pos]); + else + printk("%d, ", ((unsigned char *)(data))[pos]); + } + } + else if (opCode == 2) { // reply + for (pos=28; pos<32; pos++) { + if (pos<31) + printk("%d.", ((unsigned char *)(data))[pos]); + else + printk("%d is at ", ((unsigned char *)(data))[pos]); + } + + for (pos=22; pos<28; pos++) { + if (pos<27) + printk("%02x:", ((unsigned char *)(data))[pos]); + else + printk("%02x, ", ((unsigned char *)(data))[pos]); + } + } + + // Destination MAC + printk("Dst MAC: "); + for (pos=0; pos<6; pos++) { + if (pos<5) + printk("%02x:", ((unsigned char *)(data))[pos]); + else + printk("%02x, ", ((unsigned char *)(data))[pos]); + } + + // Source MAC + printk("Src MAC: "); + for (pos=6; pos<12; pos++) { + if (pos<11) + printk("%02x:", ((unsigned char *)(data))[pos]); + else + printk("%02x\n", ((unsigned char *)(data))[pos]); + } + + } + } // ARP ] + + if (len_ >= 34 && !bHandle) { // ICMP [ + // IP: 0x0800 + if ( (((unsigned char *)(data))[i+12] == 0x08) && + (((unsigned char *)(data))[i+13] == 0x00) && + (((unsigned char *)(data))[i+23] == 0x01) + ) { + bHandle = 1; + if ( (((unsigned char *)(data))[i+34] == 0x00) ) { + printk(KERN_INFO "%s: [ICMP] Echo Reply, ", SQN_PRT_MODULE_NAME); + } + else if ( (((unsigned char *)(data))[i+34] == 0x03) ) { + printk(KERN_INFO "%s: [ICMP] Destination Unreachable, ", SQN_PRT_MODULE_NAME); + } + else if ( (((unsigned char *)(data))[i+34] == 0x05) ) { + printk(KERN_INFO "%s: [ICMP] Redirect, ", SQN_PRT_MODULE_NAME); + } + else if ( (((unsigned char *)(data))[i+34] == 0x08) ) { + printk(KERN_INFO "%s: [ICMP] Echo Request, ", SQN_PRT_MODULE_NAME); + } + else if ( (((unsigned char *)(data))[i+34] == 0x09) ) { + printk(KERN_INFO "%s: [ICMP] Router Adventisement, ", SQN_PRT_MODULE_NAME); + } + + // Source IP + printk("Src IP: "); + for (pos=26; pos<30; pos++) { + if (pos<29) + printk("%d.", ((unsigned char *)(data))[pos]); + else + printk("%d, ", ((unsigned char *)(data))[pos]); + } + + // Destination IP + printk("Dst IP: "); + for (pos=30; pos<34; pos++) { + if (pos<33) + printk("%d.", ((unsigned char *)(data))[pos]); + else + printk("%d\n", ((unsigned char *)(data))[pos]); + } + } + } // ICMP ] + + if (len_ >= 300 && !bHandle) { // DHCP [ + // IP: 0x0800, UDP: 0x11, port: 0x0044, 0x0043 + if ( (((unsigned char *)(data))[i+12] == 0x08) && + (((unsigned char *)(data))[i+13] == 0x00) && + (((unsigned char *)(data))[i+23] == 0x11) && + + ( + (((unsigned char *)(data))[i+34] == 0x00) && + ((((unsigned char *)(data))[i+35] == 0x44) || (((unsigned char *)(data))[i+35] == 0x43)) && + (((unsigned char *)(data))[i+36] == 0x00) && + ((((unsigned char *)(data))[i+37] == 0x43) || (((unsigned char *)(data))[i+37] == 0x44)) + ) + ) { + + bHandle = 1; + pos = 282; + + while (pos < len_ && data[pos] != 255) { // while option [ + + switch ( ((unsigned char *)(data))[pos] ) { // Option case [ + + case 0: // pad + break; + + case 1: // Subnetmask + printk(KERN_INFO "%s: Subnet Mask: ", SQN_PRT_MODULE_NAME); + for (temp=0; temp<4; temp++) { + if (temp<3) + printk("%d.", ((unsigned char *)(data))[pos+2+temp]); + else + printk("%d\n", ((unsigned char *)(data))[pos+2+temp]); + } + break; + + case 51: // IP address leasetime + case 58: // T1 + case 59: // T2 + if (((unsigned char *)(data))[pos] == 51) { + printk(KERN_INFO "%s: IP Address Lease Time: ", SQN_PRT_MODULE_NAME); + printTime32(data + pos + 2); + } + + else if (((unsigned char *)(data))[pos] == 58) { + printk(KERN_INFO "%s: Renew Time Value: ", SQN_PRT_MODULE_NAME); + printTime32(data + pos + 2); + } + else if (((unsigned char *)(data))[pos] == 59) { + // printk(KERN_INFO "%s: Option: (59) Rebinding Time Value", SQN_PRT_MODULE_NAME); + // printTime32(data + pos + 2); + } + // printk(KERN_INFO "%s: Length:%d\n", SQN_PRT_MODULE_NAME, (((unsigned char *)(data))[pos+1]) ); + + break; + + case 54: // Server identifier + /* + printk(KERN_INFO "%s: Server Identifier\n", SQN_PRT_MODULE_NAME); + // printk(KERN_INFO "%s: Length:%d\n", SQN_PRT_MODULE_NAME, (((unsigned char *)(data))[pos+1]) ); + printk(KERN_INFO "%s: Server IP: ", SQN_PRT_MODULE_NAME); + for (temp=0; temp<4; temp++) { + if (temp<3) + printk("%d.", ((unsigned char *)(data))[pos+2+temp]); + else + printk("%d\n", ((unsigned char *)(data))[pos+2+temp]); + } + */ + break; + + case 53: // DHCP message type + if ((((unsigned char *)(data))[pos+2]) == 1) { + printk(KERN_INFO "%s: [DHCP Discover]\n", SQN_PRT_MODULE_NAME); + // Source IP + printk(KERN_INFO "%s: Src IP: ", SQN_PRT_MODULE_NAME); + for (temp=26; temp<30; temp++) { + if (temp<29) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Destination IP + printk(KERN_INFO "%s: Dst IP: ", SQN_PRT_MODULE_NAME); + for (temp=30; temp<34; temp++) { + if (temp<33) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Client MAC + printk(KERN_INFO "%s: Client MAC: ", SQN_PRT_MODULE_NAME); + for (temp=70; temp<76; temp++) { + if (temp<75) + printk("%02x:", ((unsigned char *)(data))[temp]); + else + printk("%02x\n", ((unsigned char *)(data))[temp]); + } + } + else if ((((unsigned char *)(data))[pos+2]) == 2) { + printk(KERN_INFO "%s: [DHCP Offer]\n", SQN_PRT_MODULE_NAME); + + // Source IP + printk(KERN_INFO "%s: Src IP: ", SQN_PRT_MODULE_NAME); + for (temp=26; temp<30; temp++) { + if (temp<29) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Destination IP + printk(KERN_INFO "%s: Dst IP: ", SQN_PRT_MODULE_NAME); + for (temp=30; temp<34; temp++) { + if (temp<33) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Your IP + printk(KERN_INFO "%s: Your IP: ", SQN_PRT_MODULE_NAME); + for (temp=58; temp<62; temp++) { + if (temp<61) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Server IP + printk(KERN_INFO "%s: Server IP: ", SQN_PRT_MODULE_NAME); + for (temp=62; temp<66; temp++) { + if (temp<65) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Client MAC + printk(KERN_INFO "%s: Client MAC: ", SQN_PRT_MODULE_NAME); + for (temp=70; temp<76; temp++) { + if (temp<75) + printk("%02x:", ((unsigned char *)(data))[temp]); + else + printk("%02x\n", ((unsigned char *)(data))[temp]); + } + } + else if ((((unsigned char *)(data))[pos+2]) == 3) { + printk(KERN_INFO "%s: [DHCP Request]\n", SQN_PRT_MODULE_NAME); + // Source IP + printk(KERN_INFO "%s: Src IP: ", SQN_PRT_MODULE_NAME); + for (temp=26; temp<30; temp++) { + if (temp<29) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Destination IP + printk(KERN_INFO "%s: Dst IP: ", SQN_PRT_MODULE_NAME); + for (temp=30; temp<34; temp++) { + if (temp<33) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Client MAC + printk(KERN_INFO "%s: Client MAC: ", SQN_PRT_MODULE_NAME); + for (temp=70; temp<76; temp++) { + if (temp<75) + printk("%02x:", ((unsigned char *)(data))[temp]); + else + printk("%02x\n", ((unsigned char *)(data))[temp]); + } + } + else if ((((unsigned char *)(data))[pos+2]) == 4) { + printk(KERN_INFO "%s: [DHCP Decline]\n", SQN_PRT_MODULE_NAME); + // Source IP + printk(KERN_INFO "%s: Src IP: ", SQN_PRT_MODULE_NAME); + for (temp=26; temp<30; temp++) { + if (temp<29) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Destination IP + printk(KERN_INFO "%s: Dst IP: ", SQN_PRT_MODULE_NAME); + for (temp=30; temp<34; temp++) { + if (temp<33) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Client IP + printk(KERN_INFO "%s: Client IP: ", SQN_PRT_MODULE_NAME); + for (temp=54; temp<58; temp++) { + if (temp<57) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Your IP + printk(KERN_INFO "%s: Your IP: ", SQN_PRT_MODULE_NAME); + for (temp=58; temp<62; temp++) { + if (temp<61) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Server IP + printk(KERN_INFO "%s: Server IP: ", SQN_PRT_MODULE_NAME); + for (temp=62; temp<66; temp++) { + if (temp<65) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Client MAC + printk(KERN_INFO "%s: Client MAC: ", SQN_PRT_MODULE_NAME); + for (temp=70; temp<76; temp++) { + if (temp<75) + printk("%02x:", ((unsigned char *)(data))[temp]); + else + printk("%02x\n", ((unsigned char *)(data))[temp]); + } + } + else if ((((unsigned char *)(data))[pos+2]) == 5) { + printk(KERN_INFO "%s: [DHCP Ack]\n", SQN_PRT_MODULE_NAME); + // Source IP + printk(KERN_INFO "%s: Src IP: ", SQN_PRT_MODULE_NAME); + for (temp=26; temp<30; temp++) { + if (temp<29) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Destination IP + printk(KERN_INFO "%s: Dst IP: ", SQN_PRT_MODULE_NAME); + for (temp=30; temp<34; temp++) { + if (temp<33) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Client IP + printk(KERN_INFO "%s: Client IP: ", SQN_PRT_MODULE_NAME); + for (temp=54; temp<58; temp++) { + if (temp<57) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Your IP + printk(KERN_INFO "%s: Your IP: ", SQN_PRT_MODULE_NAME); + for (temp=58; temp<62; temp++) { + if (temp<61) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Server IP + printk(KERN_INFO "%s: Server IP: ", SQN_PRT_MODULE_NAME); + for (temp=62; temp<66; temp++) { + if (temp<65) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Client MAC + printk(KERN_INFO "%s: Client MAC: ", SQN_PRT_MODULE_NAME); + for (temp=70; temp<76; temp++) { + if (temp<75) + printk("%02x:", ((unsigned char *)(data))[temp]); + else + printk("%02x\n", ((unsigned char *)(data))[temp]); + } + } + else if ((((unsigned char *)(data))[pos+2]) == 6) { + printk(KERN_INFO "%s: [DHCP Nack]\n", SQN_PRT_MODULE_NAME); + // Source IP + printk(KERN_INFO "%s: Src IP: ", SQN_PRT_MODULE_NAME); + for (temp=26; temp<30; temp++) { + if (temp<29) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Destination IP + printk(KERN_INFO "%s: Dst IP: ", SQN_PRT_MODULE_NAME); + for (temp=30; temp<34; temp++) { + if (temp<33) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Client IP + printk(KERN_INFO "%s: Client IP: ", SQN_PRT_MODULE_NAME); + for (temp=54; temp<58; temp++) { + if (temp<57) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Your IP + printk(KERN_INFO "%s: Your IP: ", SQN_PRT_MODULE_NAME); + for (temp=58; temp<62; temp++) { + if (temp<61) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Server IP + printk(KERN_INFO "%s: Server IP: ", SQN_PRT_MODULE_NAME); + for (temp=62; temp<66; temp++) { + if (temp<65) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Client MAC + printk(KERN_INFO "%s: Client MAC: ", SQN_PRT_MODULE_NAME); + for (temp=70; temp<76; temp++) { + if (temp<75) + printk("%02x:", ((unsigned char *)(data))[temp]); + else + printk("%02x\n", ((unsigned char *)(data))[temp]); + } + } + else if ((((unsigned char *)(data))[pos+2]) == 7) { + printk(KERN_INFO "%s: [DHCP Release]\n", SQN_PRT_MODULE_NAME); + // Source IP + printk(KERN_INFO "%s: Src IP: ", SQN_PRT_MODULE_NAME); + for (temp=26; temp<30; temp++) { + if (temp<29) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Destination IP + printk(KERN_INFO "%s: Dst IP: ", SQN_PRT_MODULE_NAME); + for (temp=30; temp<34; temp++) { + if (temp<33) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Client IP + printk(KERN_INFO "%s: Client IP: ", SQN_PRT_MODULE_NAME); + for (temp=54; temp<58; temp++) { + if (temp<57) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Your IP + printk(KERN_INFO "%s: Your IP: ", SQN_PRT_MODULE_NAME); + for (temp=58; temp<62; temp++) { + if (temp<61) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Server IP + printk(KERN_INFO "%s: Server IP: ", SQN_PRT_MODULE_NAME); + for (temp=62; temp<66; temp++) { + if (temp<65) + printk("%d.", ((unsigned char *)(data))[temp]); + else + printk("%d\n", ((unsigned char *)(data))[temp]); + } + + // Client MAC + printk(KERN_INFO "%s: Client MAC: ", SQN_PRT_MODULE_NAME); + for (temp=70; temp<76; temp++) { + if (temp<75) + printk("%02x:", ((unsigned char *)(data))[temp]); + else + printk("%02x\n", ((unsigned char *)(data))[temp]); + } + } + else { + printk(KERN_INFO "%s: Type: Unknown\n", SQN_PRT_MODULE_NAME); + } + break; + + case 61: // Client identifier + printk(KERN_INFO "%s: Client identifier\n", SQN_PRT_MODULE_NAME); + printk(KERN_INFO "%s: Client MAC: ", SQN_PRT_MODULE_NAME); + for (temp=0; temp<6; temp++) { + if (temp<5) + printk("%02x:", ((unsigned char *)(data))[pos+3+temp]); + else + printk("%02x\n", ((unsigned char *)(data))[pos+3+temp]); + } + break; + + default: + break; + + } // Option case ] + + // This might go wrong if a mallformed packet is received. + // Maybe from a bogus server which is instructed to reply + // with invalid data and thus causing an exploit. + // My head hurts... but I think it's solved by the checking + // for pos= 34 && !bHandle) { // HTTP [ + // IP: 0x0800, TCP: 0x06, port: 0x0050 (80) + if ( (((unsigned char *)(data))[i+12] == 0x08) && + (((unsigned char *)(data))[i+13] == 0x00) && + (((unsigned char *)(data))[i+23] == 0x06) && + ( + ((((unsigned char *)(data))[i+34] == 0x00) && (((unsigned char *)(data))[i+35] == 0x50)) || + ((((unsigned char *)(data))[i+36] == 0x00) && (((unsigned char *)(data))[i+37] == 0x50)) + ) + ) { + bHandle = 1; + printk(KERN_INFO "%s: [HTTP] request, ", SQN_PRT_MODULE_NAME); + + // Source IP + printk("Src IP: "); + for (pos=26; pos<30; pos++) { + if (pos<29) + printk("%d.", ((unsigned char *)(data))[pos]); + else + printk("%d, ", ((unsigned char *)(data))[pos]); + } + + // Destination IP + printk("Dst IP: "); + for (pos=30; pos<34; pos++) { + if (pos<33) + printk("%d.", ((unsigned char *)(data))[pos]); + else + printk("%d\n", ((unsigned char *)(data))[pos]); + } + } + } // HTTP ] + + if (len_ >= 34 && !bHandle) { // DNS [ + // IP: 0x0800, UDP: 0x11, port: 0x0035 + if ( (((unsigned char *)(data))[i+12] == 0x08) && + (((unsigned char *)(data))[i+13] == 0x00) && + (((unsigned char *)(data))[i+23] == 0x11) && + ( + ((((unsigned char *)(data))[i+34] == 0x00) && (((unsigned char *)(data))[i+35] == 0x35)) || + ((((unsigned char *)(data))[i+36] == 0x00) && (((unsigned char *)(data))[i+37] == 0x35)) + ) + ) { + bHandle = 1; + printk(KERN_INFO "%s: [DNS] query, ", SQN_PRT_MODULE_NAME); + + // Source IP + printk("Src IP: "); + for (pos=26; pos<30; pos++) { + if (pos<29) + printk("%d.", ((unsigned char *)(data))[pos]); + else + printk("%d, ", ((unsigned char *)(data))[pos]); + } + + // Destination IP + printk("Dst IP: "); + for (pos=30; pos<34; pos++) { + if (pos<33) + printk("%d.", ((unsigned char *)(data))[pos]); + else + printk("%d\n", ((unsigned char *)(data))[pos]); + } + } + } // DNS ] + + else if (len_ >= 34 && !bHandle) { // NTP [ + // IP: 0x0800, UDP: 0x11, port: 0x007b + if ( (((unsigned char *)(data))[i+12] == 0x08) && + (((unsigned char *)(data))[i+13] == 0x00) && + (((unsigned char *)(data))[i+23] == 0x11) && + (((unsigned char *)(data))[i+34] == 0x00) && + (((unsigned char *)(data))[i+35] == 0x7b) + ) { + bHandle = 1; + printk(KERN_INFO "%s: [NTP] Sync active, ", SQN_PRT_MODULE_NAME); + + // Source IP + printk("Src IP: "); + for (pos=26; pos<30; pos++) { + if (pos<29) + printk("%d.", ((unsigned char *)(data))[pos]); + else + printk("%d, ", ((unsigned char *)(data))[pos]); + } + + // Destination IP + printk("Dst IP: "); + for (pos=30; pos<34; pos++) { + if (pos<33) + printk("%d.", ((unsigned char *)(data))[pos]); + else + printk("%d\n", ((unsigned char *)(data))[pos]); + } + } + } // NTP ] + + if (len_ >= 12 && !bHandle) { // IPv6 [ + // IPv6: 0x86DD, UDP: 0x11 + if ( (((unsigned char *)(data))[i+12] == 0x86) && + (((unsigned char *)(data))[i+13] == 0xDD) + ) { + bHandle = 1; + printk(KERN_INFO "%s: [IPv6] Network packets, ", SQN_PRT_MODULE_NAME); + + // Source IP + printk("Dst MAC: "); + for (pos=0; pos<6; pos++) { + if (pos<5) + printk("%d:", ((unsigned char *)(data))[pos]); + else + printk("%d, ", ((unsigned char *)(data))[pos]); + } + + // Destination IP + printk("Src MAC: "); + for (pos=6; pos<12; pos++) { + if (pos<11) + printk("%d:", ((unsigned char *)(data))[pos]); + else + printk("%d\n", ((unsigned char *)(data))[pos]); + } + } + } // IPv6 ] + + if (len_ >= 34 && !bHandle) { // Unknown UDP [ + // IP: 0x0800, UDP: 0x11 + if ( (((unsigned char *)(data))[i+12] == 0x08) && + (((unsigned char *)(data))[i+13] == 0x00) && + (((unsigned char *)(data))[i+23] == 0x11) + ) { + bHandle = 1; + printk(KERN_INFO "%s: [UDP] Network packets, ", SQN_PRT_MODULE_NAME); + + // Source IP + printk("Src IP: "); + for (pos=26; pos<30; pos++) { + if (pos<29) + printk("%d.", ((unsigned char *)(data))[pos]); + else + printk("%d, ", ((unsigned char *)(data))[pos]); + } + + // Destination IP + printk("Dst IP: "); + for (pos=30; pos<34; pos++) { + if (pos<33) + printk("%d.", ((unsigned char *)(data))[pos]); + else + printk("%d, ", ((unsigned char *)(data))[pos]); + } + + printk("Port: %d%d\n", ((unsigned char *)(data))[i+34], ((unsigned char *)(data))[i+35]); + } + } // Unknown ] + + if (len_ >= 34 && !bHandle) { // Unknown TCP [ + // IP: 0x0800, TCP: 0x06 + if ( (((unsigned char *)(data))[i+12] == 0x08) && + (((unsigned char *)(data))[i+13] == 0x00) && + (((unsigned char *)(data))[i+23] == 0x06) + ) { + bHandle = 1; + printk(KERN_INFO "%s: [TCP] Network packets, ", SQN_PRT_MODULE_NAME); + + // Source IP + printk("Src IP: "); + for (pos=26; pos<30; pos++) { + if (pos<29) + printk("%d.", ((unsigned char *)(data))[pos]); + else + printk("%d, ", ((unsigned char *)(data))[pos]); + } + + // Destination IP + printk("Dst IP: "); + for (pos=30; pos<34; pos++) { + if (pos<33) + printk("%d.", ((unsigned char *)(data))[pos]); + else + printk("%d, ", ((unsigned char *)(data))[pos]); + } + + printk("Port: %d%d\n", ((unsigned char *)(data))[i+34], ((unsigned char *)(data))[i+35]); + } + } // Unknown ] + + // Andrew 0903 + // printk(KERN_INFO "%s: %s: %04x ", SQN_PRT_MODULE_NAME, (prefix), i); + } // if (i % width == 0) + + // Andrew 0903 + // printk("%02x ", ((unsigned char *)(data))[i++]); + if ((i % width == 0) || (i == len_)) + printk("\n"); + } +} + + +#define MAX_DUMP_LEN 48 + +void sqn_pr_info_dump_rawdata(char *prefix, unsigned char *data, unsigned int len) { + unsigned int i = 0; + unsigned int width = 16; + unsigned int len_ = (unsigned int)(len); + + if (len_ > MAX_DUMP_LEN) { + len_ = MAX_DUMP_LEN; + } + + // sequans_xxx: RX PDU: 0000 ff ff ff ff ff ff 00 1e 90 21 0b d4 08 00 45 00 + while (i < len_) { + if (i % width == 0) + printk(KERN_INFO "%s: %s: %04x ", SQN_PRT_MODULE_NAME, (prefix), i); + + printk("%02x ", ((unsigned char *)(data))[i++]); + + if ((i % width == 0) || (i == len_)) + printk("\n"); + } +} + +int sqn_filter_packet_check(char *prefix, unsigned char *data, unsigned int len) { + unsigned int i = 0, pos = 0, temp = 0; + unsigned int width = 16; + unsigned int len_ = (unsigned int)(len); + + char buf[LARGESTRING]; + + int bHandle = 0, bFilter = 0; + + if (i < len_) { + // Unblocked list: + if (len_ >= 40 && !bHandle) { // ARP [ + if ( (((unsigned char *)(data))[i+12] == 0x08) && + (((unsigned char *)(data))[i+13] == 0x06) ) { + bHandle = 1; + bFilter = 0; + } + } // ARP ] + + if (len_ >= 34 && !bHandle) { // ICMP [ + // IP: 0x0800 + if ( (((unsigned char *)(data))[i+12] == 0x08) && + (((unsigned char *)(data))[i+13] == 0x00) && + (((unsigned char *)(data))[i+23] == 0x01) + ) { + bHandle = 1; + bFilter = 0; + } + } // ICMP ] + + if (len_ >= 300 && !bHandle) { // DHCP [ + // IP: 0x0800, UDP: 0x11, port: 0x0044, 0x0043 + if ( (((unsigned char *)(data))[i+12] == 0x08) && + (((unsigned char *)(data))[i+13] == 0x00) && + (((unsigned char *)(data))[i+23] == 0x11) && + + ( + (((unsigned char *)(data))[i+34] == 0x00) && + ((((unsigned char *)(data))[i+35] == 0x44) || (((unsigned char *)(data))[i+35] == 0x43)) && + (((unsigned char *)(data))[i+36] == 0x00) && + ((((unsigned char *)(data))[i+37] == 0x43) || (((unsigned char *)(data))[i+37] == 0x44)) + ) + ) { + + bHandle = 1; + bFilter = 0; + } + } // DHCP ] + + if (len_ >= 34 && !bHandle) { // HTTP [ + // IP: 0x0800, TCP: 0x06, port: 0x0050 (80) + if ( (((unsigned char *)(data))[i+12] == 0x08) && + (((unsigned char *)(data))[i+13] == 0x00) && + (((unsigned char *)(data))[i+23] == 0x06) && + ( + ((((unsigned char *)(data))[i+34] == 0x00) && (((unsigned char *)(data))[i+35] == 0x50)) || + ((((unsigned char *)(data))[i+36] == 0x00) && (((unsigned char *)(data))[i+37] == 0x50)) + ) + ) { + sqn_pr_info("Drop HTTP packets len:%d\n", len_); + bHandle = 1; + bFilter = 1; + } + } // HTTP ] + + if (len_ >= 34 && !bHandle) { // DNS [ + // IP: 0x0800, UDP: 0x11, port: 0x0035 + if ( (((unsigned char *)(data))[i+12] == 0x08) && + (((unsigned char *)(data))[i+13] == 0x00) && + (((unsigned char *)(data))[i+23] == 0x11) && + ( + ((((unsigned char *)(data))[i+34] == 0x00) && (((unsigned char *)(data))[i+35] == 0x35)) || + ((((unsigned char *)(data))[i+36] == 0x00) && (((unsigned char *)(data))[i+37] == 0x35)) + ) + ) { + bHandle = 1; + bFilter = 0; + } + } // DNS ] + + else if (len_ >= 34 && !bHandle) { // NTP [ + // IP: 0x0800, UDP: 0x11, port: 0x007b + if ( (((unsigned char *)(data))[i+12] == 0x08) && + (((unsigned char *)(data))[i+13] == 0x00) && + (((unsigned char *)(data))[i+23] == 0x11) && + (((unsigned char *)(data))[i+34] == 0x00) && + (((unsigned char *)(data))[i+35] == 0x7b) + ) { + sqn_pr_info("Drop NTP packets len:%d\n", len_); + bHandle = 1; + bFilter = 1; + } + } // NTP ] + + // Block list: + if (len_ >= 12 && !bHandle) { // IPv6 [ + // IPv6: 0x86DD, UDP: 0x11 + if ( (((unsigned char *)(data))[i+12] == 0x86) && + (((unsigned char *)(data))[i+13] == 0xDD) + ) { + sqn_pr_info("Drop IPv6 packets len:%d\n", len_); + bHandle = 1; + bFilter = 1; + } + } // IPv6 ] + + if (len_ >= 34 && !bHandle) { // Unknown UDP [ + // IP: 0x0800, UDP: 0x11 + if ( (((unsigned char *)(data))[i+12] == 0x08) && + (((unsigned char *)(data))[i+13] == 0x00) && + (((unsigned char *)(data))[i+23] == 0x11) + ) { + sqn_pr_info("Drop UDP packets len:%d\n", len_); + bHandle = 1; + bFilter = 1; + } + } // Unknown UDP ] + + if (len_ >= 34 && !bHandle) { // Unknown TCP [ + // IP: 0x0800, TCP: 0x06 + if ( (((unsigned char *)(data))[i+12] == 0x08) && + (((unsigned char *)(data))[i+13] == 0x00) && + (((unsigned char *)(data))[i+23] == 0x06) + ) { + sqn_pr_info("Drop TCP packets len:%d\n", len_); + bHandle = 1; + bFilter = 1; + } + } // Unknown TCP ] + } + + return bFilter; +} + +// print the data as a 32bits time-value +void printTime32(u_char *data) { + int t = (data[0] << 24) + (data[1] << 16) + (data[2] <<8 ) + data[3]; + printk("%d (", t); + if (t > SPERW) { printk("%dw", t / (SPERW)); t %= SPERW; } + if (t > SPERD) { printk("%dd", t / (SPERD)); t %= SPERD; } + if (t > SPERH) { printk("%dh", t / (SPERH)); t %= SPERH; } + if (t > SPERM) { printk("%dm", t / (SPERM)); t %= SPERM; } + if (t > 0) printk("%ds", t); + printk(")"); +} --- a/drivers/net/wimax/SQN/msg.h +++ b/drivers/net/wimax/SQN/msg.h @@ -19,7 +19,6 @@ #include "version.h" - #define sqn_pr(level, fmt, arg...) \ do { \ char kthread_name[TASK_COMM_LEN] = { 0 }; \ @@ -34,18 +33,10 @@ do { \ } while (0) -#if defined(DEBUG) - -#ifdef SQN_DEBUG_LEVEL_INFO -#define DEBUG_LEVEL KERN_INFO -#else -#define DEBUG_LEVEL KERN_DEBUG -#endif - -#define sqn_pr_dbg(fmt, arg...) sqn_pr(DEBUG_LEVEL, fmt, ##arg) +#define SQN_DEBUG_DUMP 1 #ifdef SQN_DEBUG_DUMP - +#define DEBUG_LEVEL KERN_INFO #define sqn_pr_dbg_dump(prefix, data, len) \ do { \ unsigned int i = 0; \ @@ -60,13 +51,22 @@ do { \ printk("\n"); \ } \ } while (0) - #else /* !SQN_DEBUG_DUMP */ #define sqn_pr_dbg_dump(prefix, data, len) do {} while (0) - #endif /* SQN_DEBUG_DUMP */ + +#if defined(DEBUG) + +#ifdef SQN_DEBUG_LEVEL_INFO +#define DEBUG_LEVEL KERN_INFO +#else +#define DEBUG_LEVEL KERN_DEBUG +#endif + +#define sqn_pr_dbg(fmt, arg...) sqn_pr(DEBUG_LEVEL, fmt, ##arg) + #ifdef SQN_DEBUG_TRACE #define sqn_pr_enter() sqn_pr_dbg("%s\n", "enter") @@ -82,7 +82,6 @@ do { \ #else /* !DEBUG */ #define sqn_pr_dbg(fmt, arg...) do {} while (0) -#define sqn_pr_dbg_dump(prefix, data, len) do {} while (0) #define sqn_pr_enter() do {} while (0) #define sqn_pr_leave() do {} while (0) @@ -100,11 +99,17 @@ do { \ pr_err("%s: " fmt, SQN_MODULE_NAME, ##arg) +void sqn_pr_info_dump(char *prefix, unsigned char *data, unsigned int len); +void sqn_pr_info_dump_rawdata(char *prefix, unsigned char *data, unsigned int len); +int sqn_filter_packet_check(char *prefix, unsigned char *data, unsigned int len); + +/* #define sqn_pr_info_dump(prefix, data, len) \ do { \ unsigned int i = 0; \ unsigned int width = 16; \ unsigned int len_ = (unsigned int)(len); \ + sqn_pr_info_trace(prefix, data, len); \ while (i < len_) { \ if (i % width == 0) \ printk(KERN_INFO "%s: %s: %04x ", \ @@ -114,6 +119,6 @@ do { \ printk("\n"); \ } \ } while (0) - +*/ #endif /* _SQN_MSG_H */ --- a/drivers/net/wimax/SQN/sdio-driver.c +++ b/drivers/net/wimax/SQN/sdio-driver.c @@ -30,6 +30,7 @@ #define DRIVER_DEBUG 0 #define SKB_DEBUG 0 #define IGNORE_CARRIER_STATE 1 +#define SDIO_CLAIM_HOST_DEBUG 0 /*******************************************************************/ /* Module parameter variables */ @@ -132,8 +133,11 @@ int sqn_hard_start_xmit(struct sk_buff * } } - if (priv->removed) - goto out; + if (priv->removed) { + spin_unlock_irqrestore(&priv->drv_lock, irq_flags); + dev_kfree_skb_any(skb); + return NETDEV_TX_LOCKED; + } if (skb->len < 1 || (skb->len > SQN_MAX_PDU_LEN)) { sqn_pr_dbg("skb length %d not in range (1, %d)\n", skb->len, @@ -229,7 +233,7 @@ static int sqn_tx_thread(void *data) if (priv->removed) { sqn_pr_dbg("adapter removed; wait to die...\n"); spin_unlock_irqrestore(&priv->drv_lock, irq_flags); - mdelay(1); + ssleep(1); continue; } spin_unlock_irqrestore(&priv->drv_lock, irq_flags); @@ -288,6 +292,10 @@ int sqn_rx_process(struct net_device *de int rc = 0; struct sqn_private *priv = netdev_priv(dev); +#if SDIO_CLAIM_HOST_DEBUG + /* sqn_pr_info("%s+\n", __func__); */ +#endif + #if DRIVER_DEBUG printk(KERN_WARNING "sqn_rx_process \n"); #endif @@ -306,6 +314,11 @@ int sqn_rx_process(struct net_device *de /* netif_receive_skb(skb); */ sqn_pr_leave(); + +#if SDIO_CLAIM_HOST_DEBUG + /* sqn_pr_info("%s-\n", __func__); */ +#endif + return rc; } --- a/drivers/net/wimax/SQN/sdio-fw.c +++ b/drivers/net/wimax/SQN/sdio-fw.c @@ -119,43 +119,58 @@ out: * this give up and try to alloc 4KB buffer if requested size bigger than * 4KB, otherwise allocate nothing and return 0. * - * @return a real size of allocated buffer or 0 if allocation failed + * @return a real size of allocated buffer or 0 if allocation failed + * + * Normal: 3912*4kB 4833*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 54312kB */ static size_t sqn_alloc_big_buffer(u8 **buf, size_t size, gfp_t gfp_flags) { size_t real_size = size; - int retries = 6; + // int retries = 6; + // int retries = 3; sqn_pr_enter(); /* Try to allocate buffer of requested size, if it failes try to * allocate a twice smaller buffer. Repeat this number of * times. */ + /* do { *buf = kmalloc(real_size, gfp_flags); + printk("%s: kmalloc %d in %x trial:%d\n", __func__, real_size, *buf, retries); + if (!(*buf)) { - real_size /= 2; - /* adjust the size to be a multiple of 4 */ + printk("%s: kmalloc %d failed, trial:%d\n", __func__, real_size, retries); + // real_size /= 2; + real_size /= 4; + // adjust the size to be a multiple of 4 real_size += real_size % 4 ? 4 - real_size % 4 : 0; } } while (retries-- > 0 && !(*buf)); + */ - /* If all retries failed, then allocate 4KB buffer */ + // If all retries failed, then allocate 4KB buffer if (!(*buf)) { - real_size = 4 * 1024; + real_size = 8 * 1024; if (size >= real_size) { *buf = kmalloc(real_size, gfp_flags); - /* If it also failed, then just return 0, indicating - * that we failed to alloc buffer */ + // printk("%s: kmalloc %d in %x\n", __func__, real_size, *buf); + + // If it also failed, then just return 0, indicating + // that we failed to alloc buffer if (!(*buf)) real_size = 0; } else { - /* We should _not_ return buffer bigger than requested */ - real_size = 0; + // We should _not_ return buffer bigger than requested + // real_size = 0; + + // printk("%s: We should _not_ return buffer bigger than requested size:%d real_size:%d\n", __func__, size, real_size); + *buf = kmalloc(size, gfp_flags); + real_size = size; } - } + } sqn_pr_leave(); @@ -478,19 +493,19 @@ static int sqn_handle_mac_addr_tag(struc sqn_pr_dbg("single mac address\n"); /* we have only one mac addr */ get_mac_addr_from_str(data, length, priv->mac_addr); - + // Andrew 0720 // ++(priv->mac_addr[ETH_ALEN - 1]) - // real MAC: 38:E6:D8:86:00:00 + // real MAC: 38:E6:D8:86:00:00 // hboot will store: 38:E6:D8:85:FF:FF (minus 1) // sdio need to recovery it by plusing 1: 38:E6:D8:86:00:00 (plus 1) - + if ((++(priv->mac_addr[ETH_ALEN - 1])) == 0x00) - if ((++(priv->mac_addr[ETH_ALEN - 2])) == 0x00) - if ((++(priv->mac_addr[ETH_ALEN - 3])) == 0x00) - if ((++(priv->mac_addr[ETH_ALEN - 4])) == 0x00) - if ((++(priv->mac_addr[ETH_ALEN - 5])) == 0x00) - ++(priv->mac_addr[ETH_ALEN - 6]); + if ((++(priv->mac_addr[ETH_ALEN - 2])) == 0x00) + if ((++(priv->mac_addr[ETH_ALEN - 3])) == 0x00) + if ((++(priv->mac_addr[ETH_ALEN - 4])) == 0x00) + if ((++(priv->mac_addr[ETH_ALEN - 5])) == 0x00) + ++(priv->mac_addr[ETH_ALEN - 6]); } else if (2 * MAC_ADDR_STRING_LEN + 1 == length) { /* we have two macs */ @@ -525,7 +540,7 @@ out: * * All fields of bootstrapper file is in BIG ENDIAN format. */ -static int sqn_load_bootstrapper(struct sdio_func *func, const u8 *data, int size) +static int sqn_load_bootstrapper(struct sdio_func *func, u8 *data, int size) { struct sqn_tlv *tlv = (struct sqn_tlv*) data; int rv = 0; @@ -673,7 +688,7 @@ int sqn_load_firmware(struct sdio_func * } sqn_pr_info("loading bootloader to the card...\n"); - if ((rv = sqn_load_bootstrapper(func, fw->data, fw->size))) + if ((rv = sqn_load_bootstrapper(func, (u8*) fw->data, fw->size))) goto out; /* boot the card */ @@ -686,6 +701,12 @@ int sqn_load_firmware(struct sdio_func * sqn_pr_info(" done\n"); out: + // To avoid kzalloc leakage in /drivers/base/firmware_class.c + if (fw) { + release_firmware(fw); + fw = NULL; + } + sqn_pr_leave(); return rv; } --- a/drivers/net/wimax/SQN/sdio-pm.c +++ b/drivers/net/wimax/SQN/sdio-pm.c @@ -24,10 +24,10 @@ #include #include #include +#include +#include -#ifdef ANDROID_KERNEL #include -#endif /* ANDROID_KERNEL */ #include "sdio-netdev.h" #include "sdio.h" @@ -36,8 +36,47 @@ #include "thp.h" #include "sdio-sqn.h" +#define SDIO_CLAIM_HOST_DEBUG 0 + +#if SDIO_CLAIM_HOST_DEBUG +#define sqn_sdio_claim_host(func) \ +({ \ + struct mmc_host *h = (func)->card->host; \ + sqn_pr_info("%s: claim_host+\n", __func__); \ + sqn_pr_info("%s: BEFORE claim: claimed %d, claim_cnt %d, claimer 0x%p\n" \ + , __func__, h->claimed, h->claim_cnt, h->claimer); \ + sdio_claim_host((func)); \ + sqn_pr_info("%s: AFTER claim: claimed %d, claim_cnt %d, claimer 0x%p\n" \ + , __func__, h->claimed, h->claim_cnt, h->claimer); \ + sqn_pr_info("%s: claim_host-\n", __func__); \ +}) + +#define sqn_sdio_release_host(func) \ +({ \ + struct mmc_host *h = (func)->card->host; \ + sqn_pr_info("%s: release_host+\n", __func__); \ + sqn_pr_info("%s: BEFORE release: claimed %d, claim_cnt %d, claimer 0x%p\n" \ + , __func__, h->claimed, h->claim_cnt, h->claimer); \ + sdio_release_host((func)); \ + sqn_pr_info("%s: AFTER release: claimed %d, claim_cnt %d, claimer 0x%p\n" \ + , __func__, h->claimed, h->claim_cnt, h->claimer); \ + sqn_pr_info("%s: release_host-\n", __func__); \ +}) +#else +#define sqn_sdio_claim_host(func) \ +({ \ + sdio_claim_host((func)); \ +}) + +#define sqn_sdio_release_host(func) \ +({ \ + sdio_release_host((func)); \ +}) +#endif + #define IGNORE_CARRIER_STATE 1 extern int mmc_wimax_get_hostwakeup_gpio(void); +extern void mmc_wimax_enable_host_wakeup(int on); enum sqn_thsp_service { #define THSP_LSP_SERVICE_BASE 0x10010000 @@ -163,8 +202,7 @@ static u32 g_last_request_pm = 0; /* TODO: move this to per-card private structure */ -static DECLARE_WAIT_QUEUE_HEAD(g_card_sleep_waitq); - +DECLARE_WAIT_QUEUE_HEAD(g_card_sleep_waitq); /* Transaction ID for lsp requests */ static u32 g_tid = 0; @@ -697,9 +735,8 @@ int sqn_wakeup_fw(struct sdio_func *func u8 need_to_unlock_wakelock = 0; sqn_pr_enter(); - sqn_pr_info("waking up the card...\n"); - + if (!wake_lock_active(&card->wakelock)) { sqn_pr_dbg("lock wake_lock\n"); wake_lock(&card->wakelock); @@ -707,7 +744,10 @@ int sqn_wakeup_fw(struct sdio_func *func } retry: - sdio_claim_host(func); + if (priv->removed) + goto out; + + sqn_sdio_claim_host(func); #define SDIO_CCCR_CCCR_SDIO_VERSION_VALUE 0x11 @@ -722,7 +762,7 @@ retry: if (rv) { sqn_pr_err("error when reading SDIO_VERSION\n"); - sdio_release_host(func); + sqn_sdio_release_host(func); goto out; } else { sqn_pr_dbg("SDIO_VERSION has been read successfully\n"); @@ -733,13 +773,16 @@ retry: if (rv) sqn_pr_err("error when writing to SQN_SOC_SIGS_LSBS: %d\n", rv); - sdio_release_host(func); + sqn_sdio_release_host(func); sqn_pr_info("wait for completion (timeout %d msec)...\n" , jiffies_to_msecs(timeout)); rv = wait_event_interruptible_timeout(g_card_sleep_waitq - , 0 == card->is_card_sleeps, timeout); + , 0 == card->is_card_sleeps || priv->removed, timeout); + + if (priv->removed) + goto out; if (-ERESTARTSYS == rv) { sqn_pr_warn("got a signal from kernel %d\n", rv); @@ -747,7 +790,7 @@ retry: rv = -1; sqn_pr_err("can't wake up the card - timeout elapsed\n"); - if (retry_cnt-- > 0) { + if (retry_cnt-- > 0 && card->is_card_sleeps) { sqn_pr_info("retry wake up\n"); goto retry; } @@ -771,22 +814,14 @@ out: return rv; } -#ifdef ANDROID_KERNEL - -extern u8 sqn_is_gpio_irq_enabled; +extern void mmc_wimax_enable_host_wakeup(int on); static void sqn_handle_android_early_suspend(struct early_suspend *h) { sqn_pr_enter(); sqn_pr_info("%s: enter\n", __func__); - if (!sqn_is_gpio_irq_enabled) { - sqn_pr_info("enable GPIO%d interrupt\n", mmc_wimax_get_hostwakeup_gpio()); - enable_irq(MSM_GPIO_TO_INT(mmc_wimax_get_hostwakeup_gpio())); - enable_irq_wake(MSM_GPIO_TO_INT(mmc_wimax_get_hostwakeup_gpio())); - - sqn_is_gpio_irq_enabled = 1; - } + mmc_wimax_enable_host_wakeup(1); sqn_pr_info("%s: leave\n", __func__); sqn_pr_leave(); @@ -798,12 +833,7 @@ static void sqn_handle_android_late_resu sqn_pr_enter(); sqn_pr_info("%s: enter\n", __func__); - if (sqn_is_gpio_irq_enabled) { - sqn_pr_info("disable GPIO%d interrupt\n", (mmc_wimax_get_hostwakeup_gpio())); - disable_irq_wake(MSM_GPIO_TO_INT(mmc_wimax_get_hostwakeup_gpio())); - disable_irq(MSM_GPIO_TO_INT(mmc_wimax_get_hostwakeup_gpio())); - sqn_is_gpio_irq_enabled = 0; - } + mmc_wimax_enable_host_wakeup(0); sqn_pr_info("%s: leave\n", __func__); sqn_pr_leave(); @@ -835,4 +865,3 @@ void unregister_android_earlysuspend(voi sqn_pr_leave(); } -#endif /* ANDROID_KERNEL */ --- a/drivers/net/wimax/SQN/sdio-sqn.h +++ b/drivers/net/wimax/SQN/sdio-sqn.h @@ -133,6 +133,7 @@ int sqn_sdio_tx_skb(struct sqn_sdio_card #define SQN_SDIO_IT_STATUS_MSBS 0x2047 /* Firmware loading registers */ +#define SQN_H_GRSTN 0x2400 #define SQN_H_CRSTN 0x2404 #define SQN_H_SDRAMCTL_RSTN 0x2414 #define SQN_H_SDRAM_NO_EMR 0x2415 --- a/drivers/net/wimax/SQN/sdio.c +++ b/drivers/net/wimax/SQN/sdio.c @@ -46,8 +46,65 @@ #define SKB_DEBUG 0 #define SDIO_CLK_DEBUG 0 -#define DUMP_NET_PKT 0 +#define DUMP_NET_PKT 1 +int dump_net_pkt = 0; +#define RESET_BY_SDIO 0 //Rollback to default disabled HW Reset +#define RESET_BY_WIMAXTRACKER 0 + +#if RESET_BY_WIMAXTRACKER +#include "sdio_netlink.h" +#endif + +#define SDIO_CLAIM_HOST_DEBUG 0 +int claim_host_dbg = 0; + +#if SDIO_CLAIM_HOST_DEBUG +#define sqn_sdio_claim_host(func) \ +({ \ + struct mmc_host *h = (func)->card->host; \ + u8 was_blocked = 0; \ + if (mmc_wimax_get_cliam_host_status()) { \ + if (h->claimed) { \ + was_blocked = 1; \ + sqn_pr_info("%s: claim_host+ current 0x%p\n", __func__, current); \ + sqn_pr_info("%s: will block\n", __func__); \ + sqn_pr_info("%s: BEFORE claim: claimed %d, claim_cnt %d, claimer 0x%p\n" \ + , __func__, h->claimed, h->claim_cnt, h->claimer); \ + } \ + } \ + sdio_claim_host((func)); \ + if (mmc_wimax_get_cliam_host_status()) { \ + if (was_blocked) { \ + sqn_pr_info("%s: AFTER claim: claimed %d, claim_cnt %d, claimer 0x%p\n" \ + , __func__, h->claimed, h->claim_cnt, h->claimer); \ + sqn_pr_info("%s: claim_host- current 0x%p\n", __func__, current); \ + } \ + } \ +}) + +#define sqn_sdio_release_host(func) \ +({ \ + /* struct mmc_host *h = (func)->card->host; */ \ + /* sqn_pr_info("%s: release_host+\n", __func__); */ \ + /* sqn_pr_info("%s: BEFORE release: claimed %d, claim_cnt %d, claimer 0x%p\n" */ \ + /* , __func__, h->claimed, h->claim_cnt, h->claimer); */ \ + sdio_release_host((func)); \ + /* sqn_pr_info("%s: AFTER release: claimed %d, claim_cnt %d, claimer 0x%p\n" */ \ + /* , __func__, h->claimed, h->claim_cnt, h->claimer); */ \ + /* sqn_pr_info("%s: release_host-\n", __func__); */ \ +}) +#else +#define sqn_sdio_claim_host(func) \ +({ \ + sdio_claim_host((func)); \ +}) + +#define sqn_sdio_release_host(func) \ +({ \ + sdio_release_host((func)); \ +}) +#endif static const struct sdio_device_id sqn_sdio_ids[] = { { SDIO_DEVICE(SDIO_VENDOR_ID_SEQUANS, SDIO_DEVICE_ID_SEQUANS_SQN1130) }, @@ -57,11 +114,24 @@ static const struct sdio_device_id sqn_s }; MODULE_DEVICE_TABLE(sdio, sqn_sdio_ids); +// Wakeup interrupt +extern void mmc_wimax_enable_host_wakeup(int on); + //HTC:WiMax power ON_OFF function and Card detect function extern int mmc_wimax_power(int on); extern void mmc_wimax_set_carddetect(int val); extern int mmc_wimax_uart_switch(int uart); extern int mmc_wimax_set_status(int on); +extern int mmc_wimax_get_hostwakeup_gpio(void); +extern int mmc_wimax_get_netlog_status(void); +extern int mmc_wimax_get_cliam_host_status(void); +extern int mmc_wimax_set_CMD53_timeout_trigger_counter(int counter); +extern int mmc_wimax_get_CMD53_timeout_trigger_counter(void); +extern int mmc_wimax_get_sdio_hw_reset(void); +extern int mmc_wimax_get_packet_filter(void); + +extern int mmc_wimax_get_netlog_withraw_status(void); +extern int mmc_wimax_get_sdio_interrupt_log(void); /*******************************************************************/ /* TX handlers */ @@ -119,10 +189,12 @@ static int sqn_sdio_get_rstn_wr_fifo_fla if (0 == card->rstn_wr_fifo_flag) { int rv = 0; - sdio_claim_host(card->func); // by daniel + + sqn_sdio_claim_host(card->func); card->rstn_wr_fifo_flag = sdio_readb(card->func, SQN_SDIO_RSTN_WR_FIFO(2), &rv); - sdio_release_host(card->func); // by daniel + + sqn_sdio_release_host(card->func); sqn_pr_dbg("RSTN_WR_FIFO2 = %d\n", card->rstn_wr_fifo_flag); if (rv) { sqn_pr_err("sdio_readb(RSTN_WR_FIFO2) - return error\n"); @@ -144,9 +216,10 @@ static int sqn_sdio_recover_after_cmd53_ sqn_pr_enter(); sqn_pr_info("Try to recovery after SDIO timeout error\n"); - sdio_claim_host(card->func); + + sqn_sdio_claim_host(card->func); sdio_writeb(card->func, 1 << card->func->num, SDIO_CCCR_IO_ABORT, &rv); - sdio_release_host(card->func); + sqn_sdio_release_host(card->func); if (rv) { sqn_pr_err("sdio_writeb(SDIO_CCCR_IO_ABORT) - return error %d\n" , rv); @@ -176,7 +249,7 @@ static int sqn_sdio_cmd52_read_buf(struc sqn_pr_enter(); sqn_pr_info("Trying to read %d bytes from 0x%x address using CMD52\n", size, addr); - sdio_claim_host(card->func); + sqn_sdio_claim_host(card->func); for (i = 0; i < size; i++) { tmpbuf[i] = sdio_readb(card->func, addr + i, &rv); if (rv) { @@ -184,7 +257,7 @@ static int sqn_sdio_cmd52_read_buf(struc break; } } - sdio_release_host(card->func); + sqn_sdio_release_host(card->func); switch (size) { case sizeof(u16): @@ -212,8 +285,7 @@ static int sqn_sdio_dump_registers(struc sqn_pr_enter(); sqn_pr_info("------------------ REG DUMP BEGIN ------------------\n"); - sdio_claim_host(card->func); - + sqn_sdio_claim_host(card->func); b8 = sdio_readb(card->func, SQN_SDIO_IT_STATUS_LSBS, &rv); if (rv) sqn_pr_err("can't read SDIO_IT_STATUS_LSBS: %d\n", rv); @@ -244,7 +316,7 @@ static int sqn_sdio_dump_registers(struc else sqn_pr_info("SQN_HTS_SIGS: 0x%x\n", b8); - sdio_release_host(card->func); + sqn_sdio_release_host(card->func); rv = sqn_sdio_cmd52_read_buf(card, &b16, sizeof(b16), SQN_SDIO_WR_FIFO_BYTESLEFT(2)); if (rv) @@ -291,11 +363,11 @@ static int sqn_sdio_get_wr_fifo_level(st sqn_pr_enter(); - sdio_claim_host(card->func); // by daniel + sqn_sdio_claim_host(card->func); /* level = sdio_readw(card->func, SQN_SDIO_WR_FIFO_LEVEL(2), &rv); */ level = sdio_readl(card->func, 0x2050, &rv); level = (u32)level >> sizeof(u16); - sdio_release_host(card->func); // by daniel + sqn_sdio_release_host(card->func); sqn_pr_dbg("SQN_SDIO_WR_FIFO_LEVEL2 = %d\n", level); if (rv) { sqn_pr_err("sdio_readw(WR_FIFO_LEVEL2) error %d\r", rv); @@ -342,13 +414,38 @@ struct sk_buff* sqn_sdio_prepare_skb_for return 0; #if DUMP_NET_PKT - if (!is_thp_packet(eth->h_source) && !is_lsp_packet(skb)) { - sqn_pr_info("----------------------------------------------------------------------\n"); + if (mmc_wimax_get_netlog_status()) { + sqn_pr_info("[PRT]-------------------------------------------------------------------\n"); sqn_pr_info("TX PDU length %d\n", skb->len); - sqn_pr_info_dump("TX PDU", skb->data, skb->len); - } + + if (is_thp_packet(eth->h_source)) { + sqn_pr_info("TX THP packet\n"); + } + else if (is_lsp_packet(skb)) { + sqn_pr_info("TX LSP packet\n"); + } + else if (!is_thp_packet(eth->h_source) && !is_lsp_packet(skb)) { + sqn_pr_info_dump("TX PDU", skb->data, skb->len); + } + } + + if (mmc_wimax_get_netlog_withraw_status()) { + // if (!is_thp_packet(eth->h_source) && !is_lsp_packet(skb)) + { + sqn_pr_info("[RAW]-------------------------------------------------------------------\n"); + sqn_pr_info("TX PDU length %d\n", skb->len); + sqn_pr_info_dump_rawdata("TX PDU", skb->data, skb->len); + } + } #endif + if (mmc_wimax_get_packet_filter()) { + if (sqn_filter_packet_check("TX PDU", skb->data, skb->len)) { + // sqn_pr_info("Drop TX packets len:%d\n", skb->len); + return 0; + } + } + /* * Real size of the PDU is data_len + 2 bytes at begining of PDU * for pdu_size + 4 bytes at the end of PDU for CRC of data @@ -413,7 +510,7 @@ int sqn_sdio_tx_skb(struct sqn_sdio_card sqn_pr_enter(); if (claim_host) - sdio_claim_host(card->func); + sqn_sdio_claim_host(card->func); rv = sdio_writesb(card->func, SQN_SDIO_RDWR_FIFO(2), skb->data, skb->len); @@ -421,7 +518,7 @@ int sqn_sdio_tx_skb(struct sqn_sdio_card sqn_pr_err("call to sdio_writesb(RDWR_FIFO2) - return error %d\n", rv); if (-ETIMEDOUT == rv) { if (claim_host) { - sdio_release_host(card->func); + sqn_sdio_release_host(card->func); claim_host = 0; } sqn_pr_info("SDIO CMD53 timeout error: TX PDU length %d, PDU[0] 0x%x, PDU[1] 0x%x\n" @@ -432,8 +529,8 @@ int sqn_sdio_tx_skb(struct sqn_sdio_card goto release; } release: - if (claim_host) - sdio_release_host(card->func); + if (claim_host) + sqn_sdio_release_host(card->func); #if SKB_DEBUG sqn_pr_info("%s: free skb [0x%p] after tx, users %d\n", __func__, skb, atomic_read(&skb->users)); #endif @@ -579,24 +676,53 @@ out: } sqn_sdio_release_wake_lock(card); - if (0 != rv) { + + if ((0 != rv) || (mmc_wimax_get_CMD53_timeout_trigger_counter())) { /* * Failed to send PDU - assume that card was removed or * crashed/reset so initiate card detection. */ - // Andrew 0424 - // Reset chip will cause WiMAX status to OFF and then SCAN, OPERATION - // Reset WiMAX chip - // It could avoid we hang in SDIO CMD53 timeout and recovery wimax again. - - sqn_pr_info("reset WiMAX chip\n"); - mmc_wimax_power(0); - mdelay(5); - mmc_wimax_power(1); - - sqn_pr_err("card seems to be dead/removed - initiate reinitialization\n"); - mmc_detect_change(card->func->card->host, 1); + if (mmc_wimax_get_CMD53_timeout_trigger_counter()) { + sqn_pr_info("Force CMD53 timeout to reset SDIO!\n"); + mmc_wimax_set_CMD53_timeout_trigger_counter(mmc_wimax_get_CMD53_timeout_trigger_counter()-1); + } + + // Reset WiMAX chip + if (mmc_wimax_get_sdio_hw_reset()) { // mmc_wimax_get_sdio_hw_reset [ + sqn_pr_info("reset WiMAX chip by SDIO\n"); + + // HW Reset + mmc_wimax_power(0); + mdelay(5); + mmc_wimax_power(1); + // To avoid re-initialized SDIO card failed + priv->removed = 1; + + sqn_pr_err("card seems to be dead/removed - initiate reinitialization\n"); + mmc_detect_change(card->func->card->host, 1); + + // SW Reset + // It could avoid we hang in SDIO CMD53 timeout and recovery wimax again. + /* + netif_carrier_off(priv->dev); + priv->removed = 1; + sqn_sdio_claim_host(card->func); + // software card reset + sdio_writeb(card->func, 0, SQN_H_GRSTN, &rv); + sqn_sdio_release_host(card->func); + mmc_detect_change(card->func->card->host, 0); + */ + } + else + { +#if RESET_BY_WIMAXTRACKER + sqn_pr_info("reset WiMAX chip by WimaxTracker\n"); + udp_broadcast(1,"ResetWimax_BySDIO\n"); +#else + sqn_pr_info("No reset WiMAX chip\n"); +#endif + } // mmc_wimax_get_sdio_hw_reset ] } drv_removed: sqn_pr_leave(); @@ -667,6 +793,12 @@ static int sqn_sdio_card_to_host(struct sqn_pr_enter(); +#if SDIO_CLAIM_HOST_DEBUG + if (mmc_wimax_get_cliam_host_status()) { + sqn_pr_info("%s+\n", __func__); + } +#endif + if (card->priv->removed) { // sqn_pr_warn("%s: card/driver is removed, do nothing\n", __func__); // Andrew 0524 goto drv_removed; @@ -682,7 +814,7 @@ static int sqn_sdio_card_to_host(struct need_to_ulock_mutex = 1; /* - * NOTE: call to sdio_claim_host() is already done + * NOTE: call to sqn_sdio_claim_host() is already done * in sqn_sdio_it_lsb() - our caller */ check_level: @@ -708,6 +840,12 @@ check_level: struct ethhdr *eth = 0; #endif u16 size = 0; + +#if SDIO_CLAIM_HOST_DEBUG + if (mmc_wimax_get_cliam_host_status()) { + sqn_pr_info("%s: 0\n", __func__); + } +#endif /* Get the size of PDU */ size = sdio_readw(card->func, SQN_SDIO_RDLEN_FIFO(2), &rv); @@ -745,23 +883,63 @@ check_level: skb_put(skb, size); #if DUMP_NET_PKT - eth = (struct ethhdr *)skb->data; - if (!is_thp_packet(eth->h_dest) && !is_lsp_packet(skb)) { - sqn_pr_info("----------------------------------------------------------------------\n"); - sqn_pr_info("RX PDU length %d\n", skb->len); - sqn_pr_info_dump("RX PDU", skb->data, skb->len); + if (mmc_wimax_get_netlog_status()) { + eth = (struct ethhdr *)skb->data; + + sqn_pr_info("[PRT]-------------------------------------------------------------------\n"); + sqn_pr_info("RX PDU length %d\n", skb->len); + + if (is_thp_packet(eth->h_dest)) { + sqn_pr_info("RX THP packet\n"); + } + else if (is_lsp_packet(skb)) { + sqn_pr_info("RX LSP packet\n"); + } + else if (!is_thp_packet(eth->h_dest) && !is_lsp_packet(skb)) { + sqn_pr_info_dump("RX PDU", skb->data, skb->len); + } + } + + if (mmc_wimax_get_netlog_withraw_status()) { + eth = (struct ethhdr *)skb->data; + // if (!is_thp_packet(eth->h_dest) && !is_lsp_packet(skb)) + { + sqn_pr_info("[RAW]-------------------------------------------------------------------\n"); + sqn_pr_info("RX PDU length %d\n", skb->len); + sqn_pr_info_dump_rawdata("RX PDU", skb->data, skb->len); + } } #endif - if (sqn_handle_lsp_packet(card->priv, skb)) - continue; + if (sqn_handle_lsp_packet(card->priv, skb)) { +#if SDIO_CLAIM_HOST_DEBUG + if (mmc_wimax_get_cliam_host_status()) { + sqn_pr_info("%s: 1\n", __func__); + } +#endif + continue; + } + /* * If we have some not LSP PDUs to read, then card is not * asleep any more, so we should notify waiters about this */ + +#if SDIO_CLAIM_HOST_DEBUG + if (mmc_wimax_get_cliam_host_status()) { + sqn_pr_info("%s: 2\n", __func__); + } +#endif + if (card->is_card_sleeps) { sqn_pr_info("got RX data, card is not asleep\n"); - signal_card_sleep_completion(card->priv); + /* signal_card_sleep_completion(card->priv); */ + card->is_card_sleeps = 0; +#if SDIO_CLAIM_HOST_DEBUG + if (mmc_wimax_get_cliam_host_status()) { + sqn_pr_info("%s: 3\n", __func__); + } +#endif } if (!card->waiting_pm_notification @@ -814,6 +992,12 @@ out: } drv_removed: + +#if SDIO_CLAIM_HOST_DEBUG + if (mmc_wimax_get_cliam_host_status()) { + sqn_pr_info("%s-\n", __func__); + } +#endif sqn_pr_leave(); return rv; } @@ -833,7 +1017,11 @@ static int sqn_sdio_it_lsb(struct sdio_f sqn_pr_enter(); - /* NOTE: call of sdio_claim_host() is already done */ +#if SDIO_CLAIM_HOST_DEBUG + /* sqn_pr_info("%s+\n", __func__); */ +#endif + + /* NOTE: call of sqn_sdio_claim_host() is already done */ /* Read the interrupt status */ status = sdio_readb(func, SQN_SDIO_IT_STATUS_LSBS, &rc); @@ -867,6 +1055,11 @@ static int sqn_sdio_it_lsb(struct sdio_f out: sqn_pr_dbg("returned code: %d\n", rc); + +#if SDIO_CLAIM_HOST_DEBUG + /* sqn_pr_info("%s-\n", __func__); */ +#endif + sqn_pr_leave(); return rc; } @@ -879,6 +1072,10 @@ static int sqn_sdio_it_msb(struct sdio_f sqn_pr_enter(); +#if SDIO_CLAIM_HOST_DEBUG + /* sqn_pr_info("%s+\n", __func__); */ +#endif + /* Read the interrupt status */ status = sdio_readb(func, SQN_SDIO_IT_STATUS_MSBS, &rc); if (rc) @@ -894,6 +1091,11 @@ static int sqn_sdio_it_msb(struct sdio_f out: sqn_pr_dbg("returned code: %d\n", rc); + +#if SDIO_CLAIM_HOST_DEBUG + /* sqn_pr_info("%s-\n", __func__); */ +#endif + sqn_pr_leave(); return rc; } @@ -912,8 +1114,23 @@ void sqn_sdio_interrupt(struct sdio_func u8 is_card_sleeps = 0; struct sqn_sdio_card *card = sdio_get_drvdata(func); +#if SDIO_CLAIM_HOST_DEBUG + struct mmc_host *h = (func)->card->host; +#endif + sqn_pr_enter(); +#if SDIO_CLAIM_HOST_DEBUG + /* sqn_pr_info("%s+\n", __func__); */ +#endif + +#if SDIO_CLAIM_HOST_DEBUG + if (mmc_wimax_get_cliam_host_status()) { + sqn_pr_info("%s+: mmc_host: claimed %d, claim_cnt %d, claimer 0x%p\n" + , __func__, h->claimed, h->claim_cnt, h->claimer); + } +#endif + sqn_sdio_it_lsb(func); spin_lock_irqsave(&card->priv->drv_lock, irq_flags); @@ -923,6 +1140,12 @@ void sqn_sdio_interrupt(struct sdio_func if (!is_card_sleeps) sqn_sdio_it_msb(func); +#if SDIO_CLAIM_HOST_DEBUG + if (mmc_wimax_get_cliam_host_status()) { + sqn_pr_info("%s-\n", __func__); + } +#endif + sqn_pr_leave(); } @@ -933,8 +1156,7 @@ static int sqn_sdio_it_enable(struct sdi int rv = 0; sqn_pr_enter(); - sdio_claim_host(func); - + sqn_sdio_claim_host(func); /* enable LSB */ enable = SQN_SDIO_IT_WR_FIFO2_WM | SQN_SDIO_IT_RD_FIFO2_WM | SQN_SDIO_IT_SW_SIGN; @@ -955,7 +1177,7 @@ static int sqn_sdio_it_enable(struct sdi goto out; } out: - sdio_release_host(func); + sqn_sdio_release_host(func); sqn_pr_dbg("returned code: %d\n", rv); sqn_pr_leave(); return rv; @@ -967,7 +1189,7 @@ static int sqn_sdio_it_disable(struct sd int rc = 0; sqn_pr_enter(); - sdio_claim_host(func); + sqn_sdio_claim_host(func); /* disable LSB */ sdio_writeb(func, 0, SQN_SDIO_IT_EN_LSBS, &rc); @@ -982,7 +1204,7 @@ static int sqn_sdio_it_disable(struct sd sqn_pr_dbg("disabled interrupt(MSB)\n"); out: sqn_pr_dbg("returned code: %d\n", rc); - sdio_release_host(func); + sqn_sdio_release_host(func); sqn_pr_leave(); return rc; } @@ -1012,7 +1234,7 @@ static void sqn_sdio_debug_test(struct s /* int val = 0; */ sqn_pr_enter(); - sdio_claim_host(func); + sqn_sdio_claim_host(func); /* sqn_pr_dbg("write SQN_SOC_SIGS_LSBS\n"); */ /* sdio_writeb(func, 1, SQN_SOC_SIGS_LSBS, &rc); */ @@ -1070,7 +1292,7 @@ static void sqn_sdio_debug_test(struct s sqn_pr_dbg("writel SQN_SDIO_WM_RD_FIFO(2) = %x\n", rc); #endif - sdio_release_host(func); + sqn_sdio_release_host(func); sqn_pr_leave(); } @@ -1119,9 +1341,9 @@ static int check_boot_from_host_mode(str int rv = 0; int status = 0; - sdio_claim_host(func); + sqn_sdio_claim_host(func); status = sdio_readb(func, SQN_H_BOOT_FROM_SPI, &rv); - sdio_release_host(func); + sqn_sdio_release_host(func); if (rv) { @@ -1218,9 +1440,9 @@ static u8 sqn_get_card_version(struct sd */ sqn_pr_info("Checking card version...\n"); - sdio_claim_host(func); + sqn_sdio_claim_host(func); version = sdio_readl(func, SQN_H_VERSION, &rv); - sdio_release_host(func); + sqn_sdio_release_host(func); if (rv) { sqn_pr_err("failed to read card version\n"); rv = 0; @@ -1257,6 +1479,11 @@ extern struct sqn_private *g_priv; struct msmsdcc_host; int msmsdcc_enable_clocks(struct msmsdcc_host *host); +void msmsdcc_disable_clocks(struct msmsdcc_host *host, int deferr); +int msmsdcc_get_sdc_clocks(struct msmsdcc_host *host); +int sqn_sdio_get_sdc_clocks(void); +void sqn_sdio_set_sdc_clocks(int on); +int sqn_sdio_notify_host_wakeup(void); static irqreturn_t wimax_wakeup_gpio_irq_handler(int irq, void *dev_id) { @@ -1271,14 +1498,64 @@ static irqreturn_t wimax_wakeup_gpio_irq // sqn_pr_info("WiMAX GPIO interrupt\n"); #endif - msmsdcc_enable_clocks(msm_host); - + // To avoid flush the logging in kmsg, remove it. + if (mmc_wimax_get_sdio_interrupt_log()) { + if (printk_ratelimit()) + sqn_pr_info("WiMAX GPIO interrupt\n"); + } + + if (!sqn_sdio_get_sdc_clocks()) { + msmsdcc_enable_clocks(msm_host); + msmsdcc_disable_clocks(msm_host, 5 * HZ); + } sqn_pr_leave(); return IRQ_HANDLED; } +int sqn_sdio_notify_host_wakeup(void) +{ + struct sqn_sdio_card *card = g_priv->card; + int rv = 0; + + sqn_pr_enter(); + + rv = sqn_wakeup_fw(card->func); + + sqn_pr_leave(); + + return rv; +} +EXPORT_SYMBOL(sqn_sdio_notify_host_wakeup); + +int sqn_sdio_get_sdc_clocks(void) +{ + struct sqn_sdio_card *card = g_priv->card; + struct msmsdcc_host *host = mmc_priv(card->func->card->host); + + return msmsdcc_get_sdc_clocks(host); +} +EXPORT_SYMBOL(sqn_sdio_get_sdc_clocks); + +void sqn_sdio_set_sdc_clocks(int on) +{ + struct sqn_sdio_card *card = g_priv->card; + struct msmsdcc_host *host = mmc_priv(card->func->card->host); + + sqn_pr_enter(); + + if (on) { + msmsdcc_enable_clocks(host); + } + else { + msmsdcc_disable_clocks(host, 0); + } + + sqn_pr_leave(); +} +EXPORT_SYMBOL(sqn_sdio_set_sdc_clocks); + int init_thp_handler(struct net_device *dev); void cleanup_thp_handler(void); @@ -1334,7 +1611,7 @@ static int sqn_sdio_probe(struct sdio_fu sqn_card->func = func; /* Activate SDIO function and register interrupt handler */ - sdio_claim_host(func); + sqn_sdio_claim_host(func); rv = sdio_enable_func(func); if (rv) @@ -1344,7 +1621,7 @@ static int sqn_sdio_probe(struct sdio_fu if (rv) goto disable; - sdio_release_host(func); + sqn_sdio_release_host(func); sdio_set_drvdata(func, sqn_card); priv = sqn_add_card(sqn_card, &func->dev); @@ -1401,8 +1678,9 @@ static int sqn_sdio_probe(struct sdio_fu if (0 == sqn_card->rstn_wr_fifo_flag) sqn_pr_warn("FW is still not started, anyway continue as is...\n"); - sqn_pr_info("setup GPIO40 for wakeup form SQN1210\n"); - rv = irq = MSM_GPIO_TO_INT(40); //GPIO_40 as wakeup + + sqn_pr_info("setup GPIO%d for wakeup form SQN1210\n", mmc_wimax_get_hostwakeup_gpio()); + rv = irq = MSM_GPIO_TO_INT(mmc_wimax_get_hostwakeup_gpio()); //HOST WAKEUP GPIO as wakeup if (rv < 0) { sqn_pr_warn("wimax-gpio to irq failed\n"); @@ -1410,14 +1688,14 @@ static int sqn_sdio_probe(struct sdio_fu } rv = request_irq(irq, wimax_wakeup_gpio_irq_handler, - req_flags, "WiMAX0", sqn_card->priv->dev); + req_flags, "WiMAX0", sqn_card->priv->dev); // IRQF_TRIGGER_RISING, raising trigger if (rv) { sqn_pr_warn("wimax-gpio request_irq failed=%d\n", rv); goto disable; } - sqn_pr_dbg("disable GPIO40 interrupt\n"); - disable_irq(MSM_GPIO_TO_INT(40)); + sqn_pr_dbg("disable GPIO%d interrupt\n", mmc_wimax_get_hostwakeup_gpio()); + disable_irq(MSM_GPIO_TO_INT(mmc_wimax_get_hostwakeup_gpio())); rv = init_thp(priv->dev); if (rv) @@ -1444,12 +1722,12 @@ err_activate_card: flush_scheduled_work(); free_netdev(priv->dev); reclaim: - sdio_claim_host(func); + sqn_sdio_claim_host(func); sdio_release_irq(func); disable: sdio_disable_func(func); release: - sdio_release_host(func); + sqn_sdio_release_host(func); sqn_sdio_free_tx_queue(sqn_card); sqn_sdio_free_rx_queue(sqn_card); @@ -1468,6 +1746,8 @@ free_card: } +extern wait_queue_head_t g_card_sleep_waitq; + static void sqn_sdio_remove(struct sdio_func *func) { struct sqn_sdio_card *sqn_card = sdio_get_drvdata(func); @@ -1477,8 +1757,8 @@ static void sqn_sdio_remove(struct sdio_ sqn_pr_enter(); - sqn_pr_info("free GPIO40 interrupt\n"); - free_irq(MSM_GPIO_TO_INT(40),sqn_card->priv->dev); + sqn_pr_info("free GPIO%d interrupt\n", mmc_wimax_get_hostwakeup_gpio()); + free_irq(MSM_GPIO_TO_INT(mmc_wimax_get_hostwakeup_gpio()),sqn_card->priv->dev); #if defined(DEBUG) sqn_sdio_print_debug_info(func); @@ -1493,6 +1773,7 @@ static void sqn_sdio_remove(struct sdio_ delay = 1000; sqn_sdio_it_disable(sqn_card->func); + wake_up_interruptible(&g_card_sleep_waitq); sqn_pr_info("wait until RX is finished\n"); count = 5; @@ -1502,8 +1783,8 @@ static void sqn_sdio_remove(struct sdio_ sqn_pr_warn("%s: failed to acquire RX mutex\n", __func__); sqn_stop_card(sqn_card->priv); - kthread_stop(sqn_card->priv->tx_thread); wake_up_interruptible(&sqn_card->priv->tx_waitq); + kthread_stop(sqn_card->priv->tx_thread); sqn_pr_info("wait until TX is finished\n"); count = 5; @@ -1512,10 +1793,10 @@ static void sqn_sdio_remove(struct sdio_ if (!rv) sqn_pr_warn("%s: failed to acquire TX mutex\n", __func__); - sdio_claim_host(func); + sqn_sdio_claim_host(func); sdio_release_irq(func); sdio_disable_func(func); - sdio_release_host(func); + sqn_sdio_release_host(func); sqn_remove_card(sqn_card->priv); @@ -1539,7 +1820,6 @@ static void sqn_sdio_remove(struct sdio_ sqn_pr_leave(); } -u8 sqn_is_gpio_irq_enabled = 0; int sqn_sdio_suspend(struct sdio_func *func, pm_message_t msg) { int rv = 0; @@ -1576,12 +1856,7 @@ int sqn_sdio_suspend(struct sdio_func *f } out: - if (!sqn_is_gpio_irq_enabled) { - sqn_pr_info("enable GPIO40 interrupt\n"); - enable_irq(MSM_GPIO_TO_INT(40)); - enable_irq_wake(MSM_GPIO_TO_INT(40)); - sqn_is_gpio_irq_enabled = 1; - } + mmc_wimax_enable_host_wakeup(1); sqn_pr_info("%s: leave\n", __func__); sqn_pr_leave(); @@ -1606,28 +1881,28 @@ int sqn_sdio_resume(struct sdio_func *fu // some TX data /* sqn_notify_host_wakeup(func); */ - if (sqn_is_gpio_irq_enabled) { - sqn_pr_info("disable GPIO40 interrupt\n"); - disable_irq_wake(MSM_GPIO_TO_INT(40)); - disable_irq(MSM_GPIO_TO_INT(40)); - sqn_is_gpio_irq_enabled = 0; - } + mmc_wimax_enable_host_wakeup(0); sqn_pr_info("%s: leave\n", __func__); sqn_pr_leave(); return rv; } +int sqn_sdio_dump_net_pkt(int on) { + + printk("[SDIO] %s: dump_net_pkt: %d\n", __func__, on); + dump_net_pkt = on; + + return 0; +} static struct sdio_driver sqn_sdio_driver = { .name = SQN_MODULE_NAME , .id_table = sqn_sdio_ids , .probe = sqn_sdio_probe , .remove = sqn_sdio_remove -#ifdef ANDROID_KERNEL , .suspend = sqn_sdio_suspend , .resume = sqn_sdio_resume -#endif }; @@ -1650,12 +1925,17 @@ static int __init sqn_sdio_init_module(v mmc_wimax_set_carddetect(1); // thp_wimax_uart_switch(1); mmc_wimax_set_status(1); - + dump_net_pkt = mmc_wimax_get_netlog_status(); + claim_host_dbg = mmc_wimax_get_cliam_host_status(); + + rc = sdio_register_driver(&sqn_sdio_driver); -#ifdef ANDROID_KERNEL register_android_earlysuspend(); -#endif /* TI_KERNEL */ + +#if RESET_BY_WIMAXTRACKER + sdio_netlink_register(); +#endif sqn_pr_info("Driver has been registered\n"); @@ -1670,9 +1950,7 @@ static void __exit sqn_sdio_exit_module( sdio_unregister_driver(&sqn_sdio_driver); -#ifdef ANDROID_KERNEL unregister_android_earlysuspend(); -#endif sqn_pr_info("Driver has been removed\n"); @@ -1681,6 +1959,10 @@ static void __exit sqn_sdio_exit_module( // thp_wimax_uart_switch(0); mmc_wimax_set_status(0); +#if RESET_BY_WIMAXTRACKER + sdio_netlink_deregister(); +#endif + sqn_pr_leave(); } --- a/drivers/net/wimax/SQN/sdio.h +++ b/drivers/net/wimax/SQN/sdio.h @@ -15,4 +15,6 @@ #include #include +int sqn_sdio_dump_net_pkt(int on); + #endif /* _SQN_SDIO_WRAPPERS_H */ --- /dev/null +++ b/drivers/net/wimax/SQN/sdio_netlink.c @@ -0,0 +1,57 @@ +#include "sdio_netlink.h" + +struct sock *netlink_sock; + +void udp_broadcast(int gid,void *payload) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + int size=strlen(payload)+1; + int len = NLMSG_SPACE(size); + void *data; + int ret; + + skb = alloc_skb(len, GFP_KERNEL); + if (!skb) + return; + nlh= NLMSG_PUT(skb, 0, 0, 0, size); + nlh->nlmsg_flags = 0; + data=NLMSG_DATA(nlh); + memcpy(data, payload, size); + NETLINK_CB(skb).pid = 0; /* from kernel */ + NETLINK_CB(skb).dst_group = gid; /* unicast */ + ret=netlink_broadcast(netlink_sock, skb, 0, gid, GFP_KERNEL); + + if (ret <0) + { + printk("[SDIO] %s send failed\n", __func__); + return; + } + return; + +nlmsg_failure: /* Used by NLMSG_PUT */ + if (skb) + kfree_skb(skb); +} + +void MyTimerFunction(unsigned long data) +{ + udp_broadcast(1,"ResetWimax_BySDIO\n"); +} + +void udp_receive(struct sk_buff *skb) +{ +} + +int sdio_netlink_register(void) +{ + netlink_sock = netlink_kernel_create(&init_net, NETLINK_USERSOCK, 0,udp_receive, NULL, THIS_MODULE); + return 0; +} + +void sdio_netlink_deregister(void) +{ + sock_release(netlink_sock->sk_socket); + printk("[SDIO] %s: netlink driver remove successfully\n", __func__); +} + --- /dev/null +++ b/drivers/net/wimax/SQN/sdio_netlink.h @@ -0,0 +1,17 @@ +#ifndef _SDIO_NETLINK_H +#define _SDIO_NETLINK_H + +#include +#include +#include +#include +#include +#include + +void udp_broadcast(int gid,void *payload); +void MyTimerFunction(unsigned long data); +void udp_receive(struct sk_buff *skb); +int sdio_netlink_register(void); +void sdio_netlink_deregister(void); + +#endif --- a/drivers/net/wimax/SQN/thp.c +++ b/drivers/net/wimax/SQN/thp.c @@ -46,6 +46,8 @@ extern bool drop_packet; const uint8_t host_macaddr[ETH_ALEN] = {0x00, 0x16, 0x08, 0xff, 0x00, 0x01}; const uint8_t ss_macaddr[ETH_ALEN] = {0x00, 0x16, 0x08, 0xff, 0x00, 0x00}; +extern int sqn_sdio_dump_net_pkt(int on); +extern int mmc_wimax_get_thp_log(void); // Queue of packets destined to the Connection Manager // TODO: check size of the queue, it's should always be one. @@ -380,9 +382,8 @@ static ssize_t thp_read(struct file *fil struct sk_buff_head *head = &to_sqntool_queue; struct sk_buff *curr = NULL; ssize_t retval; -#if THP_HEADER_DUMP const struct sqn_thp_header *th = 0; -#endif + sqn_pr_enter(); #if THP_DEBUG printk(KERN_WARNING "thp_read +\n"); @@ -427,25 +428,21 @@ static ssize_t thp_read(struct file *fil retval = -EFAULT; goto free_skb; } -#if THP_TRACE - sqn_pr_info("%s: [to_user]: len = %d\n", __func__, count); -#endif -#if THP_HEADER_DUMP - th = (struct sqn_thp_header *) curr->data; - sqn_pr_info("%s: PKTLen: %4u | TVer: 0x0%x | Flags: 0x0%x | Len: %4u" - " | SeqNum: %5u | AckNum: %5u | TLen: %5u\n", __func__ - , count - , th->transport_version - , th->flags - , be16_to_cpu(th->length) - , be16_to_cpu(th->seq_number) - , be16_to_cpu(th->ack_number) - , be32_to_cpu(th->total_length)); -#endif - sqn_pr_dbg("[to_user]: len = %d\n", count); -#ifdef SQN_DEBUG_DUMP - sqn_pr_dbg_dump("RX:", curr->data, count); -#endif + + if (mmc_wimax_get_thp_log()) { + sqn_pr_info("%s: [to_user]: len = %d\n", __func__, count); + th = (struct sqn_thp_header *) curr->data; + sqn_pr_info("%s: PKTLen: %4u | TVer: 0x0%x | Flags: 0x0%x | Len: %4u" + " | SeqNum: %5u | AckNum: %5u | TLen: %5u\n", __func__ + , count + , th->transport_version + , th->flags + , be16_to_cpu(th->length) + , be16_to_cpu(th->seq_number) + , be16_to_cpu(th->ack_number) + , be32_to_cpu(th->total_length)); + sqn_pr_dbg_dump("THP RX:", curr->data, count); + } #if SKB_DEBUG sqn_pr_info("%s: free skb [0x%p], users %d\n", __func__, curr, atomic_read(&curr->users)); @@ -477,9 +474,7 @@ static ssize_t thp_write(struct file *fi struct sk_buff *skb; struct ethhdr ethh; int size = count + ETH_HLEN; -#if THP_HEADER_DUMP const struct sqn_thp_header *th = 0; -#endif sqn_pr_enter(); #if THP_DEBUG @@ -509,25 +504,22 @@ static ssize_t thp_write(struct file *fi return -EFAULT; } skb_put(skb, count); -#if THP_TRACE - sqn_pr_info("%s: [from_user]: len = %d\n", __func__, count); -#endif -#if THP_HEADER_DUMP - th = (struct sqn_thp_header *) buf; - sqn_pr_info("%s: PKTLen: %4u | TVer: 0x0%x | Flags: 0x0%x | Len: %4u" - " | SeqNum: %5u | AckNum: %5u | TLen: %5u\n", __func__ - , count - , th->transport_version - , th->flags - , be16_to_cpu(th->length) - , be16_to_cpu(th->seq_number) - , be16_to_cpu(th->ack_number) - , be32_to_cpu(th->total_length)); -#endif - sqn_pr_dbg("[from_user]: len = %d\n", count); -#ifdef SQN_DEBUG_DUMP - sqn_pr_dbg_dump("TX:", skb->data, count); -#endif + + if (mmc_wimax_get_thp_log()) { + sqn_pr_info("%s: [from_user]: len = %d\n", __func__, count); + th = (struct sqn_thp_header *) buf; + sqn_pr_info("%s: PKTLen: %4u | TVer: 0x0%x | Flags: 0x0%x | Len: %4u" + " | SeqNum: %5u | AckNum: %5u | TLen: %5u\n", __func__ + , count + , th->transport_version + , th->flags + , be16_to_cpu(th->length) + , be16_to_cpu(th->seq_number) + , be16_to_cpu(th->ack_number) + , be32_to_cpu(th->total_length)); + + sqn_pr_dbg_dump("THP TX:", skb->data, count); + } #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) this_device->hard_start_xmit(skb, this_device); @@ -601,6 +593,14 @@ static int thp_ioctl(struct inode* dev, mmc_wimax_uart_switch(0); // USB break; + case IOCTL_SWITCH_NETLOG: + printk(KERN_WARNING "IOCTL_SWITCH_NETLOG arg=%d\n",(int)arg); + if(arg == 0) + sqn_sdio_dump_net_pkt(0); // Enable netlog + else + sqn_sdio_dump_net_pkt(1); // Disable netlog + break; + default: printk(KERN_WARNING "UNKNOWN OPERATION in thp_ioctl\n"); return -1; --- a/drivers/net/wimax/SQN/thp_ioctl.h +++ b/drivers/net/wimax/SQN/thp_ioctl.h @@ -11,11 +11,13 @@ //must be a nonnegative 8-bit number #define CMD_DROP_PACKETS CMD_BASE+0 #define CMD_SIWTCH_UART CMD_BASE+1 +#define CMD_SIWTCH_NETLOG CMD_BASE+2 //write only //arg=1, drop tx/rx packets //arg=0, normal mode #define IOCTL_DROP_PACKETS _IOW(WIMAX_DEV_IOCTLID, CMD_DROP_PACKETS, int) #define IOCTL_SWITCH_UART _IOW(WIMAX_DEV_IOCTLID, CMD_SIWTCH_UART, int) +#define IOCTL_SWITCH_NETLOG _IOW(WIMAX_DEV_IOCTLID, CMD_SIWTCH_NETLOG, int) #endif //_THP_IOCTL_H_ --- /dev/null +++ b/drivers/net/wimax/wimaxdbg/Makefile @@ -0,0 +1,10 @@ +MODULE_NAME = wimaxdbg +KDIR = /lib/modules/$(CURRENT)/build + +obj-m := $(MODULE_NAME).o +all: + @echo "making $(MODULE_NAME)" + @echo "PWD=$(PWD)" + $(MAKE) -C $(KDIR) M=$(PWD) modules +clean: + $(MAKE) -C $(KDIR) M=$(PWD) clean --- /dev/null +++ b/drivers/net/wimax/wimaxdbg/wimaxdbg.c @@ -0,0 +1,192 @@ +#include +#include +#include +#include +#include +#include + +extern int mmc_wimax_set_netlog_status(int on); +extern int mmc_wimax_set_cliam_host_status(int on); +// extern int sqn_sdio_get_sdc_clocks(void); +// extern void sqn_sdio_set_sdc_clocks(int on); +extern int mmc_wimax_set_busclk_pwrsave(int on); +extern int mmc_wimax_set_CMD53_timeout_trigger_counter(int counter); +extern int mmc_wimax_get_CMD53_timeout_trigger_counter(void); + +extern int sqn_sdio_notify_host_wakeup(void); +extern int mmc_wimax_set_thp_log(int on); +extern int mmc_wimax_set_sdio_hw_reset(int on); +extern int mmc_wimax_set_packet_filter(int on); + +extern int mmc_wimax_set_netlog_withraw_status(int on); +extern int mmc_wimax_set_sdio_interrupt_log(int on); + +#define BUF_LEN 100 + +// # insmod wimaxdbg + +static char *wimaxdbg_name=NULL; +module_param(wimaxdbg_name,charp,0); + +static int dbg_para = 0; +static struct proc_dir_entry *wimaxdbg_proc_file; + +ssize_t wimaxdbg_write(struct file *file, const char *buffer, unsigned long count, void *data) +{ + char buf[16]; + unsigned long len = count; + int n; + + printk(KERN_INFO "%d (%s)\n", (int)len, __func__); + + if (len >= sizeof(buf)) + len = sizeof(buf) - 1; + + if (copy_from_user(buf, buffer, len)) + return -EFAULT; + + buf[len] = '\0'; + + n = simple_strtol(buf, NULL, 10); + dbg_para = n; + + printk(KERN_INFO "%s: dbg_parameter:%d\n", __func__, dbg_para); + if (dbg_para < 2) { // 0: netlog off, 1: netlog on + printk(KERN_INFO "%s: mmc_wimax_set_netlog_status:%d\n", __func__, dbg_para); + mmc_wimax_set_netlog_status(dbg_para); + } + else if (dbg_para == 3) { // 3: sdc_clock off + printk(KERN_INFO "%s: sqn_sdio_set_sdc_clocks:0\n", __func__); + // sqn_sdio_set_sdc_clocks(0); // Need to insert sequans_sdio.ko first + } + else if (dbg_para == 4) { // 4: sdc_clock on + printk(KERN_INFO "%s: sqn_sdio_set_sdc_clocks:1\n", __func__); + // sqn_sdio_set_sdc_clocks(1); // Need to insert sequans_sdio.ko first + } + else if (dbg_para == 5) { // 5: claim_host debug on + printk(KERN_INFO "%s: mmc_wimax_set_cliam_host_status:1\n", __func__); + mmc_wimax_set_cliam_host_status(1); + } + else if (dbg_para == 6) { // 6: claim host debug off + printk(KERN_INFO "%s: mmc_wimax_set_cliam_host_status:0\n", __func__); + mmc_wimax_set_cliam_host_status(0); + } + else if (dbg_para == 7) { // 7: Turn off dynamic SDC CLK OFF + printk(KERN_INFO "%s: mmc_wimax_set_busclk_pwrsave:0\n", __func__); + mmc_wimax_set_busclk_pwrsave(0); + } + else if (dbg_para == 8) { // 8: Turn on dynamic SDC CLK OFF + printk(KERN_INFO "%s: mmc_wimax_set_busclk_pwrsave:1\n", __func__); + mmc_wimax_set_busclk_pwrsave(1); + } + else if (dbg_para == 9) { // 9: Disable force CMD53 timeout testing + printk(KERN_INFO "%s: mmc_wimax_set_CMD53_timeout_trigger_counter:0\n", __func__); + mmc_wimax_set_CMD53_timeout_trigger_counter(0); + } + else if (dbg_para == 10) { // 10: Force CMD53 timeout testing + printk(KERN_INFO "%s: mmc_wimax_set_CMD53_timeout_trigger_counter:1\n", __func__); + mmc_wimax_set_CMD53_timeout_trigger_counter(5); + } + else if (dbg_para == 11) { // 11: Manually re-send host wakeup + // printk(KERN_INFO "%s: sqn_sdio_notify_host_wakeup\n", __func__); + // sqn_sdio_notify_host_wakeup(); // Need to insert sequans_sdio.ko first + } + else if (dbg_para == 12) { // 12: Disable THP logging + printk(KERN_INFO "%s: mmc_wimax_set_thp_log_status:0\n", __func__); + mmc_wimax_set_thp_log(0); + } + else if (dbg_para == 13) { // 13: Enable THP logging + printk(KERN_INFO "%s: mmc_wimax_set_thp_log_status:1\n", __func__); + mmc_wimax_set_thp_log(1); + } + else if (dbg_para == 14) { // 14: Disable SDIO HW RESET, default is disabled it. + printk(KERN_INFO "%s: mmc_wimax_set_sdio_hw_reset:0\n", __func__); + mmc_wimax_set_sdio_hw_reset(0); + } + else if (dbg_para == 15) { // 15: Enable SDIO HW RESET + printk(KERN_INFO "%s: mmc_wimax_set_sdio_hw_reset:1\n", __func__); + mmc_wimax_set_sdio_hw_reset(1); + } + else if (dbg_para == 16) { // 16: Disable SDIO Packet filter + printk(KERN_INFO "%s: mmc_wimax_set_packet_filter:0\n", __func__); + mmc_wimax_set_packet_filter(0); + } + else if (dbg_para == 17) { // 17: Enable SDIO Packet filter + printk(KERN_INFO "%s: mmc_wimax_set_packet_filter:1\n", __func__); + mmc_wimax_set_packet_filter(1); + } + else if (dbg_para == 18) { // 18: Disable SDIO GPIO interrupt logging + printk(KERN_INFO "%s: mmc_wimax_set_sdio_interrupt_log:0\n", __func__); + mmc_wimax_set_sdio_interrupt_log(0); + } + else if (dbg_para == 19) { // 19: Enable SDIO GPIO interrupt logging + printk(KERN_INFO "%s: mmc_wimax_set_sdio_interrupt_log:1\n", __func__); + mmc_wimax_set_sdio_interrupt_log(1); + } + else if (dbg_para == 20) { // 20: Disable dumping raw data for network packets + printk(KERN_INFO "%s: mmc_wimax_set_netlog_withraw_status:0\n", __func__); + mmc_wimax_set_netlog_withraw_status(0); + } + else if (dbg_para == 21) { // 21: Enable dumping raw data for network packets + printk(KERN_INFO "%s: mmc_wimax_set_netlog_withraw_status:1\n", __func__); + mmc_wimax_set_netlog_withraw_status(1); + } + else { + printk(KERN_INFO "%s: None function:%d\n", __func__, dbg_para); + } + + return (len); +} + +ssize_t wimaxdbg_read(char *buf,char **start,off_t offset,int count,int *eof,void *data) +{ + int len=0; + + if(offset>0) + return 0; + + /* + sprintf(buf,"wimxdbg: %d\nsdcclk:%d\n", dbg_para, sqn_sdio_get_sdc_clocks()); + + for(len=0;lenread_proc = wimaxdbg_read; + wimaxdbg_proc_file->write_proc = wimaxdbg_write; + + dbg_para = 0; + + return 0; +} + +void wimaxdbg_cleanup(void) +{ + printk(KERN_INFO "%s: mimaxdbg_module_claen called. Module is now clean\n", __func__); + remove_proc_entry("wimaxdbg",NULL); +} + +module_init(wimaxdbg_init); +module_exit(wimaxdbg_cleanup); + +MODULE_DESCRIPTION("HTC wimaxdbg for SDIO devices"); +MODULE_AUTHOR("HTC"); +MODULE_LICENSE("GPL"); --- /dev/null +++ b/drivers/net/wimax/wimaxuart/Makefile @@ -0,0 +1,10 @@ +MODULE_NAME = wimaxuart +KDIR = /lib/modules/$(CURRENT)/build + +obj-m := $(MODULE_NAME).o +all: + @echo "making $(MODULE_NAME)" + @echo "PWD=$(PWD)" + $(MAKE) -C $(KDIR) M=$(PWD) modules +clean: + $(MAKE) -C $(KDIR) M=$(PWD) clean --- /dev/null +++ b/drivers/net/wimax/wimaxuart/wimaxuart.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include +#include + +#define BUF_LEN 100 + +// # insmod wimaxuart + +static char *wimaxuart_name=NULL; +module_param(wimaxuart_name,charp,0); + +extern int mmc_wimax_uart_switch(int uart); + +static struct proc_dir_entry *wimaxuart_proc_file; +int uart_switch = 0; + +ssize_t wimaxuart_write(struct file *file, const char *buffer, unsigned long count, void *data) +{ + char buf[16]; + unsigned long len = count; + int n; + + printk(KERN_INFO "%d (%s)\n", (int)len, __func__); + + if (len >= sizeof(buf)) + len = sizeof(buf) - 1; + + if (copy_from_user(buf, buffer, len)) + return -EFAULT; + + buf[len] = '\0'; + + n = simple_strtol(buf, NULL, 10); + uart_switch = n; + + printk("%s: uart_switch:%d\n", __func__, uart_switch); + mmc_wimax_uart_switch(uart_switch); + + return (len); +} + +ssize_t wimaxuart_read(char *buf,char **start,off_t offset,int count,int *eof,void *data) +{ + int len=0; + + if(offset>0) + return 0; + + sprintf(buf,"wimaxuart: %d\n", uart_switch); + + for(len=0;lenread_proc = wimaxuart_read; + wimaxuart_proc_file->write_proc = wimaxuart_write; + + uart_switch = 0; + + return 0; +} + +void wimaxuart_cleanup(void) +{ + printk(KERN_INFO "%s: wimaxuart_module_claen called. Module is now clean\n", __func__); + remove_proc_entry("wimaxuart",NULL); +} + +module_init(wimaxuart_init); +module_exit(wimaxuart_cleanup); + +MODULE_DESCRIPTION("HTC wimaxuart for SDIO devices"); +MODULE_AUTHOR("HTC"); +MODULE_LICENSE("GPL");