diff --git a/package/avm/ipw2100/ipw2100-0.55-2.4.patch b/package/avm/ipw2100/ipw2100-0.55-2.4.patch new file mode 100644 index 000000000..2fb6e10a0 --- /dev/null +++ b/package/avm/ipw2100/ipw2100-0.55-2.4.patch @@ -0,0 +1,1439 @@ +diff -u -p -r -b ipw2100-0.55.orig/ieee80211_crypt.c ipw2100-0.55/ieee80211_crypt.c +--- ipw2100-0.55.orig/ieee80211_crypt.c 2004-09-27 19:29:17.000000000 +0200 ++++ ipw2100-0.55/ieee80211_crypt.c 2004-09-28 21:10:53.000000000 +0200 +@@ -55,7 +55,9 @@ void ieee80211_crypt_deinit_entries(stru + + if (entry->ops) { + entry->ops->deinit(entry->priv); ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + module_put(entry->ops->owner); ++#endif + } + kfree(entry); + } +diff -u -p -r -b ipw2100-0.55.orig/ieee80211_module.c ipw2100-0.55/ieee80211_module.c +--- ipw2100-0.55.orig/ieee80211_module.c 2004-09-27 19:29:17.000000000 +0200 ++++ ipw2100-0.55/ieee80211_module.c 2004-09-28 21:10:53.000000000 +0200 +@@ -157,7 +157,9 @@ void ieee80211_free(struct ieee80211_dev + if (crypt) { + if (crypt->ops) { + crypt->ops->deinit(crypt->priv); ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + module_put(crypt->ops->owner); ++#endif + } + kfree(crypt); + ieee->crypt[i] = NULL; +diff -u -p -r -b ipw2100-0.55.orig/ieee80211_wx.c ipw2100-0.55/ieee80211_wx.c +--- ipw2100-0.55.orig/ieee80211_wx.c 2004-09-27 19:29:17.000000000 +0200 ++++ ipw2100-0.55/ieee80211_wx.c 2004-09-28 21:10:53.000000000 +0200 +@@ -237,7 +237,11 @@ int ieee80211_wx_set_encode(struct ieee8 + new_crypt->ops = ieee80211_get_crypto_ops("WEP"); + } + ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) ++#else ++ if (new_crypt->ops) ++#endif + new_crypt->priv = new_crypt->ops->init(key); + + if (!new_crypt->ops || !new_crypt->priv) { +diff -u -p -r -b ipw2100-0.55.orig/ipw2100.c ipw2100-0.55/ipw2100.c +--- ipw2100-0.55.orig/ipw2100.c 2004-09-27 19:29:17.000000000 +0200 ++++ ipw2100-0.55/ipw2100.c 2004-09-28 21:10:53.000000000 +0200 +@@ -358,6 +358,10 @@ static void ipw2100_queues_initialize(st + static void ipw2100_queues_free(struct ipw2100_priv *priv); + static int ipw2100_queues_allocate(struct ipw2100_priv *priv); + ++static void ipw2100_proc_cleanup(void); ++static void ipw2100_proc_dev_cleanup(struct ipw2100_priv *priv); ++static int ipw2100_proc_dev_init(struct ipw2100_priv *priv); ++ + static inline int ipw2100_hw_is_adapter_in_system(struct net_device *dev) + { + return (dev->base_addr && +@@ -3064,26 +3068,35 @@ static void ipw2100_msg_free(struct ipw2 + priv->msg_buffers = NULL; + } + +-static ssize_t show_pci(struct device *d, char *buf) ++static struct proc_dir_entry *ipw2100_proc = NULL; ++ ++static int proc_get_pci(char *page, char **start, ++ off_t offset, int count, ++ int *eof, void *data) + { +- struct pci_dev *pdev = container_of(d, struct pci_dev, dev); +- char * out = buf; +- int i, j; ++ struct net_device *dev = data; ++ struct ipw2100_priv *priv = ipw2100_netdev(dev); ++ struct pci_dev *pdev = priv->pdev; ++ int i, j, len; + u32 val; + +- out += sprintf(out, "PCI Configuration Data\n"); ++ ++ len = 0; ++ ++ len += snprintf(page + len, count - len, "PCI Configuration Data\n"); ++ + for (i = 0; i < 16; i++) { +- out += sprintf(out, "[%08X] ", i * 16); ++ len += snprintf(page + len, count - len, "[%08X] ", i * 16); + for (j = 0; j < 16; j += 4) { + pci_read_config_dword(pdev, i * 16 + j, &val); +- out += sprintf(out, "%08X ", val); ++ len += snprintf(page + len, count - len, "%08X ", val); + } +- out += sprintf(out, "\n"); ++ len += snprintf(page + len, count - len, "\n"); + } + +- return out - buf; ++ *eof = 1; ++ return len; + } +-static DEVICE_ATTR(pci, S_IRUGO, show_pci, NULL); + + + #define IPW2100_REG(x) { IPW_ ##x, #x } +@@ -3263,37 +3276,48 @@ const struct { + }; + + +-static ssize_t show_registers(struct device *d, char *buf) ++static int proc_get_registers(char *page, char **start, ++ off_t offset, int count, ++ int *eof, void *data) + { ++ struct net_device *dev = data; + int i; +- struct ipw2100_priv *priv = dev_get_drvdata(d); +- struct net_device *dev = priv->ndev; +- char * out = buf; ++ int len = 0; + u32 val = 0; + +- out += sprintf(out, "%30s [Address ] : Hex\n", "Register"); ++ len += snprintf(page + len, count - len, ++ "%30s [Address ] : Hex\n", "Register"); + +- for (i = 0; i < (sizeof(hw_data) / sizeof(*hw_data)); i++) { ++ for (i = 0; ++ i < (sizeof(hw_data) / sizeof(*hw_data)); ++ i++) { + read_register(dev, hw_data[i].addr, &val); +- out += sprintf(out, "%30s [%08X] : %08X\n", +- hw_data[i].name, hw_data[i].addr, val); ++ ++ len += snprintf(page + len, count - len, ++ "%30s [%08X] : %08X\n", ++ hw_data[i].name, hw_data[i].addr, ++ val); + } + +- return out - buf; ++ *eof = 1; ++ return len; + } +-static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL); + + +-static ssize_t show_hardware(struct device *d, char *buf) ++static int proc_get_hw(char *page, char **start, ++ off_t offset, int count, ++ int *eof, void *data) + { +- struct ipw2100_priv *priv = dev_get_drvdata(d); +- struct net_device *dev = priv->ndev; +- char * out = buf; ++ struct net_device *dev = data; + int i; ++ int len = 0; + +- out += sprintf(out, "%30s [Address ] : Hex\n", "NIC entry"); ++ len += snprintf(page + len, count - len, ++ "%30s [Address ] : Hex\n", "NIC entry"); + +- for (i = 0; i < (sizeof(nic_data) / sizeof(*nic_data)); i++) { ++ for (i = 0; ++ i < (sizeof(nic_data) / sizeof(*nic_data)); ++ i++) { + u8 tmp8; + u16 tmp16; + u32 tmp32; +@@ -3301,163 +3325,213 @@ static ssize_t show_hardware(struct devi + switch (nic_data[i].size) { + case 1: + read_nic_byte(dev, nic_data[i].addr, &tmp8); +- out += sprintf(out, "%30s [%08X] : %02X\n", ++ len += snprintf(page + len, count - len, ++ "%30s [%08X] : %02X\n", + nic_data[i].name, nic_data[i].addr, + tmp8); + break; + case 2: + read_nic_word(dev, nic_data[i].addr, &tmp16); +- out += sprintf(out, "%30s [%08X] : %04X\n", ++ len += snprintf(page + len, count - len, ++ "%30s [%08X] : %04X\n", + nic_data[i].name, nic_data[i].addr, + tmp16); + break; + case 4: + read_nic_dword(dev, nic_data[i].addr, &tmp32); +- out += sprintf(out, "%30s [%08X] : %08X\n", ++ len += snprintf(page + len, count - len, ++ "%30s [%08X] : %08X\n", + nic_data[i].name, nic_data[i].addr, + tmp32); + break; + } + } +- return out - buf; ++ *eof = 1; ++ return len; + } +-static DEVICE_ATTR(hardware, S_IRUGO, show_hardware, NULL); + + +-static ssize_t show_memory(struct device *d, char *buf) ++static int proc_set_memory(struct file *file, const char *buffer, ++ unsigned long count, void *data) + { +- struct ipw2100_priv *priv = dev_get_drvdata(d); +- struct net_device *dev = priv->ndev; +- static unsigned long loop = 0; ++ struct net_device *dev = data; ++ struct ipw2100_priv *priv = ipw2100_netdev(dev); ++ char buf[] = "0000"; ++ unsigned long len = (sizeof(buf) - 1) > count ? count : ++ sizeof(buf) - 1; ++ char *p = buf; ++ ++ if (copy_from_user(buf, buffer, len)) { ++ IPW_DEBUG_INFO("can't copy data from userspace\n"); ++ /* stupid? yes, but how do I signal an error here? */ ++ return count; ++ } else ++ buf[len] = 0; ++ ++ if (p[0] == '1' || (tolower(p[0]) == 'o' && tolower(p[1] == 'n'))) { ++ printk(KERN_INFO "%s: Setting memory dump to RAW mode.\n", ++ dev->name); ++ priv->dump_raw = 1; ++ } else if (p[0] == '0' || ++ (tolower(p[0]) == 'o' && tolower(p[1] == 'f'))) { ++ printk(KERN_INFO "%s: Setting memory dump to HEX mode.\n", ++ dev->name); ++ priv->dump_raw = 0; ++ } else if (tolower(p[0]) == 'r') { ++ printk(KERN_INFO "%s: Resetting firmware snapshot.\n", ++ dev->name); ++ ipw2100_snapshot_free(priv); ++ } else ++ printk(KERN_INFO "%s: Usage: 0|on = HEX, 1|off = RAW, " ++ "reset = clear memory snapshot\n", ++ dev->name); ++ ++ return count; ++} ++ ++static int proc_get_memory(char *page, char **start, ++ off_t offset, int count, ++ int *eof, void *data) ++{ ++ struct net_device *dev = data; ++ struct ipw2100_priv *priv = ipw2100_netdev(dev); + int len = 0; +- u32 buffer[4]; ++ static unsigned long loop = 0; ++ u32 buf[4]; + int i; + char line[81]; + +- if (loop >= 0x30000) ++ if (offset == 0) + loop = 0; + +- /* sysfs provides us PAGE_SIZE buffer */ +- while (len < PAGE_SIZE - 128 && loop < 0x30000) { ++ /* If we've reached EOF or the user is cutting is short, then ++ * restart the counter and return 0 bytes */ ++ if (loop >= 0x30000) { ++ *start = NULL; ++ *eof = 1; ++ return 0; ++ } ++ ++ /* Return around 2k per pass... */ ++ while (count - len > 256 && ++ len < 2048 && ++ loop < 0x30000) { + + if (priv->snapshot[0]) for (i = 0; i < 4; i++) +- buffer[i] = *(u32 *)SNAPSHOT_ADDR(loop + i * 4); ++ buf[i] = *(u32 *)SNAPSHOT_ADDR(loop + i * 4); + else for (i = 0; i < 4; i++) +- read_nic_dword(dev, loop + i * 4, &buffer[i]); ++ read_nic_dword(dev, loop + i * 4, &buf[i]); + + if (priv->dump_raw) +- len += sprintf(buf + len, ++ len += snprintf(page + len, count - len, + "%c%c%c%c" + "%c%c%c%c" + "%c%c%c%c" + "%c%c%c%c", +- ((u8*)buffer)[0x0], +- ((u8*)buffer)[0x1], +- ((u8*)buffer)[0x2], +- ((u8*)buffer)[0x3], +- ((u8*)buffer)[0x4], +- ((u8*)buffer)[0x5], +- ((u8*)buffer)[0x6], +- ((u8*)buffer)[0x7], +- ((u8*)buffer)[0x8], +- ((u8*)buffer)[0x9], +- ((u8*)buffer)[0xa], +- ((u8*)buffer)[0xb], +- ((u8*)buffer)[0xc], +- ((u8*)buffer)[0xd], +- ((u8*)buffer)[0xe], +- ((u8*)buffer)[0xf]); ++ ((u8*)buf)[0x0], ++ ((u8*)buf)[0x1], ++ ((u8*)buf)[0x2], ++ ((u8*)buf)[0x3], ++ ((u8*)buf)[0x4], ++ ((u8*)buf)[0x5], ++ ((u8*)buf)[0x6], ++ ((u8*)buf)[0x7], ++ ((u8*)buf)[0x8], ++ ((u8*)buf)[0x9], ++ ((u8*)buf)[0xa], ++ ((u8*)buf)[0xb], ++ ((u8*)buf)[0xc], ++ ((u8*)buf)[0xd], ++ ((u8*)buf)[0xe], ++ ((u8*)buf)[0xf]); + else +- len += sprintf(buf + len, "%s\n", +- snprint_line(line, sizeof(line), +- (u8*)buffer, 16, loop)); ++ len += snprintf(page + len, count - len, "%s\n", ++ snprint_line( ++ line, sizeof(line), (u8*)buf, ++ 16, loop)); ++ + loop += 16; + } + +- return len; +-} +- +-static ssize_t store_memory(struct device *d, const char *buf, size_t count) +-{ +- struct ipw2100_priv *priv = dev_get_drvdata(d); +- struct net_device *dev = priv->ndev; +- const char *p = buf; +- +- if (count < 1) +- return count; +- +- if (p[0] == '1' || +- (count >= 2 && tolower(p[0]) == 'o' && tolower(p[1]) == 'n')) { +- printk(KERN_INFO "%s: Setting memory dump to RAW mode.\n", +- dev->name); +- priv->dump_raw = 1; +- +- } else if (p[0] == '0' || (count >= 2 && tolower(p[0]) == 'o' && +- tolower(p[1]) == 'f')) { +- printk(KERN_INFO "%s: Setting memory dump to HEX mode.\n", +- dev->name); +- priv->dump_raw = 0; +- +- } else if (tolower(p[0]) == 'r') { +- printk(KERN_INFO "%s: Resetting firmware snapshot.\n", +- dev->name); +- ipw2100_snapshot_free(priv); +- +- } else +- printk(KERN_INFO "%s: Usage: 0|on = HEX, 1|off = RAW, " +- "reset = clear memory snapshot\n", +- dev->name); ++ /* see comment in fs/proc/generic.c proc_file_read */ ++ if (len) ++ *start = (char*)len; ++ else ++ *eof = 1; + +- return count; ++ return len; + } +-static DEVICE_ATTR(memory, S_IWUSR|S_IRUGO, show_memory, store_memory); + + +-static ssize_t show_ordinals(struct device *d, char *buf) ++static int proc_get_ordinals(char *page, char **start, ++ off_t offset, int count, ++ int *eof, void *data) + { +- struct ipw2100_priv *priv = dev_get_drvdata(d); +- u32 val = 0; ++ struct net_device *dev = data; ++ struct ipw2100_priv *priv = ipw2100_netdev(dev); + int len = 0; + u32 val_len; ++ u32 val = 0; + static int loop = 0; + +- if (loop >= sizeof(ord_data) / sizeof(*ord_data)) ++ if (offset == 0) + loop = 0; + +- /* sysfs provides us PAGE_SIZE buffer */ +- while (len < PAGE_SIZE - 128 && ++ /* If we've reached EOF or the user is cutting is short, then ++ * restart the counter and return 0 bytes */ ++ if (loop >= (sizeof(ord_data) / sizeof(*ord_data))) { ++ *start = NULL; ++ *eof = 1; ++ return 0; ++ } ++ ++ /* Return around 2k per pass... */ ++ while (count - len > 256 && ++ len < 2048 && + loop < (sizeof(ord_data) / sizeof(*ord_data))) { + + val_len = sizeof(u32); + + if (ipw2100_get_ordinal(priv, ord_data[loop].index, &val, + &val_len)) +- len += sprintf(buf + len, "[0x%02X] = ERROR %s\n", ++ len += snprintf(page + len, count - len, ++ "[0x%02X] = ERROR %s\n", + ord_data[loop].index, + ord_data[loop].desc); + else +- len += sprintf(buf + len, "[0x%02X] = 0x%08X %s\n", +- ord_data[loop].index, val, +- ord_data[loop].desc); ++ len += snprintf(page + len, count - len, ++ "[0x%02X] = 0x%08X %s\n", ++ ord_data[loop].index, ++ val, ord_data[loop].desc); ++ + loop++; + } + ++ /* see comment in fs/proc/generic.c proc_file_read */ ++ if (len) ++ *start = (char*)len; ++ else ++ *eof = 1; ++ + return len; + } +-static DEVICE_ATTR(ordinals, S_IRUGO, show_ordinals, NULL); +- + +-static ssize_t show_version(struct device *d, char *buf) ++static int proc_get_version(char *page, char **start, ++ off_t offset, int count, ++ int *eof, void *data) + { +- struct ipw2100_priv *priv = dev_get_drvdata(d); +- char * out = buf; +- char tmp[MAX_FW_VERSION_LEN]; ++ struct net_device *dev = data; ++ struct ipw2100_priv *priv = ipw2100_netdev(dev); + int err; ++ int len = 0; ++ char tmp[MAX_FW_VERSION_LEN]; + +- out += sprintf(out, "hardware : 0x%04X\n", ++ len += snprintf(page + len, count - len, ++ "hardware : 0x%04X\n", + priv->pdev->subsystem_device); + +- out += sprintf(out, "driver : " DRV_VERSION " [" ++ len += snprintf(page + len, count - len, ++ "driver : " DRV_VERSION " [" + #ifdef CONFIG_IEEE80211_NOWEP + " !WEP" + #else +@@ -3470,53 +3544,66 @@ static ssize_t show_version(struct devic + #endif + " ]\n"); + +- out += sprintf(out, "build date : " __DATE__ "\n"); +- out += sprintf(out, "build time : " __TIME__ "\n"); +- out += sprintf(out, "eeprom : %d\n", priv->eeprom_version); ++ len += snprintf(page + len, count - len, ++ "build date : " __DATE__ "\n"); + ++ len += snprintf(page + len, count - len, ++ "build time : " __TIME__ "\n"); ++ ++ len += snprintf(page + len, count - len, ++ "eeprom : %d\n", priv->eeprom_version); + err = ipw2100_get_ucodeversion(priv, tmp, sizeof(tmp)); + if (err < 0) +- out += sprintf(out, "ucode : error\n"); ++ len += snprintf(page + len, count - len, ++ "ucode : error\n"); + else +- out += sprintf(out, "ucode : %s\n", tmp); +- ++ len += snprintf(page + len, count - len, ++ "ucode : %s\n", tmp); + err = ipw2100_get_fwversion(priv, tmp, sizeof(tmp)); + if (err < 0) +- out += sprintf(out, "firmware : error\n"); ++ len += snprintf(page + len, count - len, ++ "firmware : error\n"); + else +- out += sprintf(out, "firmware : %s\n", tmp); ++ len += snprintf(page + len, count - len, ++ "firmware : %s\n", tmp); + +- out += sprintf(out, "firmware img : 0x%04X\n", +- priv->firmware_version); ++ len += snprintf(page + len, count - len, ++ "firmware img : 0x%04X\n", priv->firmware_version); + +- out += sprintf(out, "firmware mode: %s\n", ++ len += snprintf(page + len, count - len, ++ "firmware mode: %s\n", + priv->ctx->port_type == MONITOR ? "RFMON" : + priv->ctx->port_type == IBSS ? "IBSS" : "BSS"); + +- return out - buf; ++ *eof = 1; ++ return len; + } +-static DEVICE_ATTR(version, S_IRUGO, show_version, NULL); + +- +-static ssize_t show_stats(struct device *d, char *buf) ++static int proc_get_stats(char *page, char **start, ++ off_t offset, int count, ++ int *eof, void *data) + { +- struct ipw2100_priv *priv = dev_get_drvdata(d); +- char * out = buf; ++ struct net_device *dev = data; ++ struct ipw2100_priv *priv = ipw2100_netdev(dev); ++ int len = 0; + +- out += sprintf(out, "interrupts: %d {tx: %d, rx: %d, other: %d}\n", ++ len += snprintf(page + len, count - len, ++ "interrupts: %d {tx: %d, rx: %d, other: %d}\n", + priv->interrupts, priv->tx_interrupts, + priv->rx_interrupts, priv->inta_other); +- out += sprintf(out, "firmware resets: %d\n", priv->resets); +- out += sprintf(out, "firmware hangs: %d\n", priv->hangs); ++ len += snprintf(page + len, count - len, ++ "firmware resets: %d\n", priv->resets); ++ len += snprintf(page + len, count - len, ++ "firmware hangs: %d\n", priv->hangs); + #ifdef CONFIG_IPW_DEBUG +- out += sprintf(out, "packet mismatch image: %s\n", ++ len += snprintf(page + len, count - len, ++ "packet mismatch image: %s\n", + priv->snapshot[0] ? "YES" : "NO"); + #endif + +- return out - buf; ++ *eof = 1; ++ return len; + } +-static DEVICE_ATTR(stats, S_IRUGO, show_stats, NULL); +- + + #ifdef CONFIG_IPW2100_PROMISC + int ipw2100_enable_monitor(struct ipw2100_priv *priv, u32 channel) +@@ -3614,12 +3701,17 @@ int ipw2100_switch_mode(struct ipw2100_p + return 0; + } + +-static ssize_t show_internals(struct device *d, char *buf) ++static int proc_get_internals(char *page, char **start, ++ off_t offset, int count, ++ int *eof, void *data) + { +- struct ipw2100_priv *priv = dev_get_drvdata(d); ++ struct net_device *dev = data; ++ struct ipw2100_priv *priv = ipw2100_netdev(dev); + int len = 0; + +-#define DUMP_VAR(x,y) len += sprintf(buf + len, # x ": %" # y "\n", priv-> x) ++#define DUMP_VAR(x,y) \ ++ len += snprintf(page + len, count - len, \ ++ # x ": %" # y "\n", priv-> x) + + DUMP_VAR(connected, d); + DUMP_VAR(connected ? get_seconds() - priv->connect_start : 0, lu); +@@ -3660,20 +3752,23 @@ static ssize_t show_internals(struct dev + DUMP_VAR(ieee->scans, d); + DUMP_VAR(reset_backoff, d); + ++ *eof = 1; + return len; + } +-static DEVICE_ATTR(internals, S_IRUGO, show_internals, NULL); +- + +-static ssize_t show_bssinfo(struct device *d, char *buf) ++static int proc_get_bssinfo(char *page, ++ char **start, ++ off_t offset, ++ int count, int *eof, void *data) + { +- struct ipw2100_priv *priv = dev_get_drvdata(d); ++ int len = 0; ++ struct net_device *dev = data; ++ struct ipw2100_priv *priv = ipw2100_netdev(dev); ++ int ret; ++ int length; + char essid[IW_ESSID_MAX_SIZE + 1]; + u8 bssid[ETH_ALEN]; + u32 chan = 0; +- char * out = buf; +- int length; +- int ret; + + memset(essid, 0, sizeof(essid)); + memset(bssid, 0, sizeof(bssid)); +@@ -3697,23 +3792,26 @@ static ssize_t show_bssinfo(struct devic + IPW_DEBUG_INFO("failed querying ordinals at line %d\n", + __LINE__); + +- out += sprintf(out, "ESSID: %s\n", essid); +- out += sprintf(out, "BSSID: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ len += snprintf(page + len, count - len, "ESSID: %s\n", essid); ++ len += snprintf(page + len, count - len, ++ "BSSID: %02x:%02x:%02x:%02x:%02x:%02x\n", + bssid[0], bssid[1], bssid[2], + bssid[3], bssid[4], bssid[5]); +- out += sprintf(out, "Channel: %d\n", chan); ++ len += snprintf(page + len, count - len, "Channel: %d\n", chan); + +- return out - buf; ++ *eof = 1; ++ return len; + } +-static DEVICE_ATTR(bssinfo, S_IRUGO, show_bssinfo, NULL); +- + +-static ssize_t show_txqueue(struct device *d, char *buf) ++static int proc_get_txqueue(char *page, ++ char **start, ++ off_t offset, ++ int count, int *eof, void *data) + { +- struct ipw2100_priv *priv = dev_get_drvdata(d); +- struct net_device *dev = priv->ndev; +- char * out = buf; ++ int len = 0; + u32 tbdr_r, tbdr_w; ++ struct net_device *dev = data; ++ struct ipw2100_priv *priv = ipw2100_netdev(dev); + + IPW_DEBUG_INFO("enter\n"); + +@@ -3724,25 +3822,29 @@ static ssize_t show_txqueue(struct devic + + IPW_DEBUG_INFO("after register read\n"); + +- out += sprintf(out, ++ len += snprintf(page, count, + "Tx Queue\nnic:\n\tread index=%d\n\twrite index=%d\n", + tbdr_r, tbdr_w); +- out += sprintf(out, "drv:\n\tread index=%d\n\twrite index=%d\n", ++ len += snprintf(page + len, count - len, ++ "drv:\n\tread index=%d\n\twrite index=%d\n", + priv->tx_queue.oldest, + priv->tx_queue.next); ++ *eof = 1; + + IPW_DEBUG_INFO("exit\n"); +- return out - buf; +-} +-static DEVICE_ATTR(txqueue, S_IRUGO, show_txqueue, NULL); + ++ return len; ++} + +-static ssize_t show_rxqueue(struct device *d, char *buf) ++static int proc_get_rxqueue(char *page, ++ char **start, ++ off_t offset, ++ int count, int *eof, void *data) + { +- struct ipw2100_priv *priv = dev_get_drvdata(d); +- struct net_device *dev = priv->ndev; +- char * out = buf; ++ int len = 0; + u32 rbdr_r, rbdr_w; ++ struct net_device *dev = data; ++ struct ipw2100_priv *priv = ipw2100_netdev(dev); + + IPW_DEBUG_INFO("enter\n"); + +@@ -3751,33 +3853,37 @@ static ssize_t show_rxqueue(struct devic + + IPW_DEBUG_INFO("after register read\n"); + +- out += sprintf(out, ++ len += snprintf(page, count, + "Rx Queue\nnic:\n\tread index=%d\n\twrite index=%d\n", + rbdr_r, rbdr_w); +- out += sprintf(out, ++ len += snprintf(page + len, count - len, + "drv:\n\tread index=NOT USED\n\twrite index=%d\n", + priv->rx_queue.next); + ++ *eof = 1; ++ + IPW_DEBUG_INFO("exit\n"); +- return out - buf; ++ ++ return len; + } +-static DEVICE_ATTR(rxqueue, S_IRUGO, show_rxqueue, NULL); + + +-#ifdef CONFIG_IPW_DEBUG +-static ssize_t show_debug_level(struct device_driver *d, char *buf) ++static int proc_get_debug_level(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) + { +- char * out = buf; ++ int len = 0; + int i; + + if (!IPW_DEBUG_ENABLED) + return 0; + +- out += sprintf(out, "%-25s\tHex SET Decimal\n", "Description"); ++ len += snprintf(page + len, count - len, ++ "%-25s\tHex SET Decimal\n", ++ "Description"); + for (i = 0; i < sizeof(ipw2100_debug_levels) / + sizeof(struct ipw2100_dl); i++) { +- out += sprintf( +- out, "%-25s\t0x%08lX [%c] %lu\n", ++ len += snprintf( ++ page + len, count - len, "%-25s\t0x%08lX [%c] %lu\n", + ipw2100_debug_levels[i].name, + ipw2100_debug_levels[i].value, + (ipw2100_debug_level & ipw2100_debug_levels[i].value) ? +@@ -3785,14 +3891,16 @@ static ssize_t show_debug_level(struct d + ipw2100_debug_levels[i].value); + } + +- out += sprintf(out, "debug_level = 0x%08lX (* = enabled)\n", ++ len += snprintf(page + len, count - len, ++ "debug_level = 0x%08lX (* = enabled)\n", + ipw2100_debug_level); + +- return out - buf; ++ *eof = 1; ++ return len; + } + +-static ssize_t store_debug_level(struct device_driver *d, const char *buf, +- size_t count) ++static int proc_set_debug_level(struct file *file, const char *buf, ++ unsigned long count, void *data) + { + char buffer[] = "0x00000000"; + unsigned long len = +@@ -3804,7 +3912,10 @@ static ssize_t store_debug_level(struct + if (!IPW_DEBUG_ENABLED) + return 0; + +- strncpy(buffer, buf, len); ++ if (copy_from_user(buffer, buf, len)) { ++ IPW_DEBUG_INFO("can't copy data from userspace\n"); ++ return count; ++ } else + buffer[len] = 0; + + if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { +@@ -3835,25 +3946,25 @@ static ssize_t store_debug_level(struct + } + } + +- return len; ++ return count; + } +-static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, show_debug_level, +- store_debug_level); +-#endif /* CONFIG_IPW_DEBUG */ + + +-static ssize_t show_fatal_error(struct device *d, char *buf) ++static int proc_get_fatal_error(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) + { +- struct ipw2100_priv *priv = dev_get_drvdata(d); +- char * out = buf; +- int errors = 0; ++ struct net_device *dev = data; ++ struct ipw2100_priv *priv = ipw2100_netdev(dev); ++ int len = 0; + int i; ++ int errors = 0; + + if (priv->fatal_error) +- out += sprintf(out, "Current error: 0x%08X\n", +- priv->fatal_error); ++ len += snprintf(page + len, count - len, ++ "Current error: 0x%08X\n", priv->fatal_error); + else +- out += sprintf(out, "No current error condition.\n"); ++ len += snprintf(page + len, count - len, ++ "No current error condition.\n"); + + for (i = 1; i <= IPW2100_ERROR_QUEUE; i++) { + if (!priv->fatal_errors[(priv->fatal_index - i) % +@@ -3861,59 +3972,70 @@ static ssize_t show_fatal_error(struct d + continue; + + if (!errors) +- out += sprintf(out, "Up to last %d errors:\n", ++ len += snprintf(page + len, count - len, ++ "Up to last %d errors:\n", + IPW2100_ERROR_QUEUE); +- out += sprintf(out, "%d. Error: 0x%08X\n", i, ++ len += snprintf(page + len, count - len, ++ "%d. Error: 0x%08X\n", i, + priv->fatal_errors[(priv->fatal_index - i) % + IPW2100_ERROR_QUEUE]); + errors++; + } + + if (!errors) +- out += sprintf(out, "No errors encountered.\n"); ++ len += snprintf(page + len, count - len, ++ "No errors encountered.\n"); + + #ifdef CONFIG_IPW_DEBUG +- out += sprintf(out, "Packet mismatch image: %s\n", ++ len += snprintf(page + len, count - len, ++ "Packet mismatch image: %s\n", + priv->snapshot[0] ? "YES" : "NO"); + #endif + + if (priv->fatal_error) +- out += sprintf(out, ++ len += snprintf(page + len, count - len, + "`echo 0 > fatal_error` to force firmware " +- "restart and clear current error condition.\n"); ++ "restart and clear current error " ++ "condition.\n"); + +- return out - buf; ++ *eof = 1; ++ return len; + } + +-static ssize_t store_fatal_error(struct device *d, const char *buf, +- size_t count) ++static int proc_set_fatal_error(struct file *file, const char *buffer, ++ unsigned long count, void *data) + { +- struct ipw2100_priv *priv = dev_get_drvdata(d); ++ struct net_device *dev = data; ++ struct ipw2100_priv *priv = ipw2100_netdev(dev); + schedule_reset(priv); + return count; + } +-static DEVICE_ATTR(fatal_error, S_IWUSR|S_IRUGO, show_fatal_error, store_fatal_error); +- + +-static ssize_t show_cardmem(struct device *d, char *buf) ++static int proc_get_cardmem(char *page, ++ char **start, ++ off_t offset, ++ int count, int *eof, void *data) + { +- struct ipw2100_priv *priv = dev_get_drvdata(d); +- struct net_device *dev = priv->ndev; +- char * out = buf; +- u32 dword; ++ int len = 0; ++ struct net_device *dev = data; ++ struct ipw2100_priv *priv = ipw2100_netdev(dev); ++ u32 d; + +- read_nic_dword(dev, priv->proc_cardmemaddr, &dword); ++ read_nic_dword(dev, priv->proc_cardmemaddr, &d); + +- out += sprintf(out, "cardmem addr[0x%08x] = 0x%08x (%d)\n", +- priv->proc_cardmemaddr, dword, dword); ++ len += snprintf(page, count, ++ "cardmem addr[0x%08x] = 0x%08x (%d)\n", ++ priv->proc_cardmemaddr, d, d); + +- return out - buf; ++ *eof = 1; ++ return len; + } + +-static ssize_t store_cardmem(struct device *d, const char *buf, size_t count) ++static int proc_set_cardmemaddr(struct file *file, const char *buf, ++ unsigned long count, void *data) + { +- struct ipw2100_priv *priv = dev_get_drvdata(d); +- struct net_device *dev = priv->ndev; ++ struct net_device *dev = data; ++ struct ipw2100_priv *priv = ipw2100_netdev(dev); + char buffer[] = "00000000"; + unsigned long len = + (sizeof(buffer) - 1) > count ? count : sizeof(buffer) - 1; +@@ -3922,7 +4044,11 @@ static ssize_t store_cardmem(struct devi + + IPW_DEBUG_INFO("enter\n"); + +- strncpy(buffer, buf, len); ++ if (copy_from_user(buffer, buf, len)) { ++ IPW_DEBUG_INFO("can't copy data from userspace\n"); ++ /* stupid? yes, but how do I signal an error here? */ ++ return count; ++ } else + buffer[len] = 0; + + if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { +@@ -3942,24 +4068,32 @@ static ssize_t store_cardmem(struct devi + } + + IPW_DEBUG_INFO("exit\n"); +- return len; ++ return count; + } +-static DEVICE_ATTR(cardmem, S_IWUSR | S_IRUGO, show_cardmem, store_cardmem); +- + +-static ssize_t show_scan_age(struct device *d, char *buf) ++static int proc_get_scan_age(char *page, ++ char **start, ++ off_t offset, ++ int count, int *eof, void *data) + { +- struct ipw2100_priv *priv = dev_get_drvdata(d); ++ int len = 0; ++ struct net_device *dev = (struct net_device *) data; ++ struct ipw2100_priv *priv = ipw2100_netdev(dev); + +- return sprintf(buf, "Scan entries will expire after %u missed scans. " ++ len += snprintf(page, count, ++ "Scan entries will expire after %u missed scans. " + "(default is %u, 0 = never expire)\n", + priv->ieee->scan_age, DEFAULT_MAX_SCAN_AGE); ++ ++ *eof = 1; ++ return len; + } + +-static ssize_t store_scan_age(struct device *d, const char *buf, size_t count) ++static int proc_set_scan_age(struct file *file, const char *buf, ++ unsigned long count, void *data) + { +- struct ipw2100_priv *priv = dev_get_drvdata(d); +- struct net_device *dev = priv->ndev; ++ struct net_device *dev = (struct net_device *) data; ++ struct ipw2100_priv *priv = ipw2100_netdev(dev); + char buffer[] = "00000000"; + unsigned long len = + (sizeof(buffer) - 1) > count ? count : sizeof(buffer) - 1; +@@ -3968,7 +4102,11 @@ static ssize_t store_scan_age(struct dev + + IPW_DEBUG_INFO("enter\n"); + +- strncpy(buffer, buf, len); ++ if (copy_from_user(buffer, buf, len)) { ++ IPW_DEBUG_INFO("can't copy data from userspace\n"); ++ /* stupid? yes, but how do I signal an error here? */ ++ return count; ++ } else + buffer[len] = 0; + + if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { +@@ -3987,37 +4125,24 @@ static ssize_t store_scan_age(struct dev + } + + IPW_DEBUG_INFO("exit\n"); +- return len; +-} +-static DEVICE_ATTR(scan_age, S_IWUSR | S_IRUGO, show_scan_age, store_scan_age); +- +- +-static ssize_t show_rf_kill(struct device *d, char *buf) +-{ +- struct ipw2100_priv *priv = dev_get_drvdata(d); +- char * out = buf; +- +- if (priv->manual_disable) +- out += sprintf(out, "Radio disabled by manual switch.\n"); +- else if (priv->hw_features & HW_FEATURE_RFKILL) +- out += sprintf(out, "Radio is %s by RF switch\n", +- ipw2100_get_rf_switch(priv) ? +- "disabled" : "enabled"); +- else +- out += sprintf(out, +- "Your hardware does not have an RF switch\n"); +- +- return out - buf; ++ return count; + } + +-static ssize_t store_rf_kill(struct device *d, const char *buf, size_t count) ++static int proc_set_state(struct file *file, const char *buf, ++ unsigned long count, void *data) + { +- struct ipw2100_priv *priv = dev_get_drvdata(d); +- int state; ++ struct net_device *dev = (struct net_device *) data; ++ struct ipw2100_priv *priv = ipw2100_netdev(dev); ++ char state; + + IPW_DEBUG_INFO("enter\n"); + +- sscanf(buf, "%d", &state); ++ if (copy_from_user(&state, buf, 1)) { ++ IPW_DEBUG_INFO("can't copy data from userspace\n"); ++ /* stupid? yes, but how do I signal an error here? */ ++ return count; ++ } ++ + switch (state) { + case 0: /* Turn off Manual Disable */ + if (priv->manual_disable) { +@@ -4052,31 +4177,323 @@ static ssize_t store_rf_kill(struct devi + IPW_DEBUG_INFO("exit\n"); + return count; + } +-static DEVICE_ATTR(rf_kill, S_IWUSR|S_IRUGO, show_rf_kill, store_rf_kill); + ++static int proc_get_state(char *page, ++ char **start, ++ off_t offset, ++ int count, int *eof, void *data) ++{ ++ int len = 0; ++ struct net_device *dev = data; ++ struct ipw2100_priv *priv = ipw2100_netdev(dev); + +-static struct attribute *ipw2100_sysfs_entries[] = { +- &dev_attr_hardware.attr, +- &dev_attr_registers.attr, +- &dev_attr_ordinals.attr, +- &dev_attr_pci.attr, +- &dev_attr_version.attr, +- &dev_attr_stats.attr, +- &dev_attr_internals.attr, +- &dev_attr_txqueue.attr, +- &dev_attr_rxqueue.attr, +- &dev_attr_bssinfo.attr, +- &dev_attr_memory.attr, +- &dev_attr_cardmem.attr, +- &dev_attr_scan_age.attr, +- &dev_attr_fatal_error.attr, +- &dev_attr_rf_kill.attr, +- NULL, +-}; ++ if (priv->manual_disable) ++ len += snprintf(page, count, ++ "Radio disabled by manual switch.\n"); ++ else if (priv->hw_features & HW_FEATURE_RFKILL) ++ len += snprintf(page, count, "Radio is %s by RF switch\n", ++ ipw2100_get_rf_switch(priv) ? ++ "disabled" : "enabled"); ++ else ++ len += snprintf(page, count, ++ "Your hardware does not have an RF switch\n"); + +-static struct attribute_group ipw2100_attribute_group = { +- .attrs = ipw2100_sysfs_entries, +-}; ++ *eof = 1; ++ return len; ++} ++ ++ ++int ipw2100_proc_dev_init(struct ipw2100_priv *priv) ++{ ++ struct proc_dir_entry *e; ++ ++ IPW_DEBUG_INFO("enter %s\n", priv->ndev->name); ++ ++ priv->dir_dev = create_proc_entry(priv->ndev->name, ++ S_IFDIR | S_IRUGO | S_IXUGO, ++ ipw2100_proc); ++ if (!priv->dir_dev) { ++ printk(KERN_ERR ++ "Unable to initialize /proc/net/ipw2100/%s\n", ++ priv->ndev->name); ++ goto fail; ++ } ++ ++ e = create_proc_read_entry("hw", S_IFREG | S_IRUGO, ++ priv->dir_dev, proc_get_hw, priv->ndev); ++ if (!e) { ++ printk(KERN_ERR ++ "Unable to initialize " ++ "/proc/net/ipw2100/%s/hw\n", ++ priv->ndev->name); ++ goto fail; ++ } ++ ++ e = create_proc_read_entry("registers", S_IFREG | S_IRUGO, ++ priv->dir_dev, proc_get_registers, priv->ndev); ++ if (!e) { ++ printk(KERN_ERR ++ "Unable to initialize " ++ "/proc/net/ipw2100/%s/registers\n", ++ priv->ndev->name); ++ goto fail; ++ } ++ ++ e = create_proc_read_entry("ordinals", S_IFREG | S_IRUGO, ++ priv->dir_dev, proc_get_ordinals, priv->ndev); ++ if (!e) { ++ printk(KERN_ERR ++ "Unable to initialize " ++ "/proc/net/ipw2100/%s/ordinals\n", ++ priv->ndev->name); ++ goto fail; ++ } ++ ++ e = create_proc_read_entry("pci", S_IFREG | S_IRUGO, ++ priv->dir_dev, proc_get_pci, priv->ndev); ++ if (!e) { ++ printk(KERN_ERR ++ "Unable to initialize " ++ "/proc/net/ipw2100/%s/pci\n", ++ priv->ndev->name); ++ goto fail; ++ } ++ ++ e = create_proc_read_entry("version", S_IFREG | S_IRUGO, ++ priv->dir_dev, proc_get_version, priv->ndev); ++ if (!e) { ++ printk(KERN_ERR ++ "Unable to initialize " ++ "/proc/net/ipw2100/%s/version\n", ++ priv->ndev->name); ++ goto fail; ++ } ++ ++ e = create_proc_read_entry("stats", S_IFREG | S_IRUGO, ++ priv->dir_dev, proc_get_stats, priv->ndev); ++ if (!e) { ++ printk(KERN_ERR ++ "Unable to initialize " ++ "/proc/net/ipw2100/%s/stats\n", ++ priv->ndev->name); ++ goto fail; ++ } ++ ++ e = create_proc_read_entry("internals", S_IFREG | S_IRUGO, ++ priv->dir_dev, proc_get_internals, priv->ndev); ++ if (!e) { ++ printk(KERN_ERR ++ "Unable to initialize " ++ "/proc/net/ipw2100/%s/internals\n", ++ priv->ndev->name); ++ goto fail; ++ } ++ ++ e = create_proc_read_entry("txqueue", S_IFREG | S_IRUGO, ++ priv->dir_dev, proc_get_txqueue, priv->ndev); ++ if (!e) { ++ printk(KERN_ERR ++ "Unable to initialize " ++ "/proc/net/ipw2100/%s/txqueue\n", ++ priv->ndev->name); ++ goto fail; ++ } ++ ++ e = create_proc_read_entry("rxqueue", S_IFREG | S_IRUGO, ++ priv->dir_dev, proc_get_rxqueue, priv->ndev); ++ if (!e) { ++ printk(KERN_ERR ++ "Unable to initialize " ++ "/proc/net/ipw2100/%s/rxqueue\n", ++ priv->ndev->name); ++ goto fail; ++ } ++ ++ e = create_proc_read_entry("bssinfo", S_IFREG | S_IRUGO, ++ priv->dir_dev, proc_get_bssinfo, priv->ndev); ++ if (!e) { ++ printk(KERN_ERR ++ "Unable to initialize " ++ "/proc/net/ipw2100/%s/bssinfo\n", ++ priv->ndev->name); ++ goto fail; ++ } ++ ++ e = create_proc_entry("memory", S_IFREG | S_IRUGO | S_IWUSR, ++ priv->dir_dev); ++ if (e) { ++ e->read_proc = proc_get_memory; ++ e->write_proc = proc_set_memory; ++ e->data = priv->ndev; ++ } else { ++ printk(KERN_ERR ++ "Unable to initialize " ++ "/proc/net/ipw2100/%s/memory\n", ++ priv->ndev->name); ++ goto fail; ++ } ++ ++ e = create_proc_entry("cardmem", S_IFREG | S_IRUGO | S_IWUSR, ++ priv->dir_dev); ++ if (e) { ++ e->read_proc = proc_get_cardmem; ++ e->write_proc = proc_set_cardmemaddr; ++ e->data = priv->ndev; ++ } else { ++ printk(KERN_ERR ++ "Unable to initialize " ++ "/proc/net/ipw2100/%s/cardmem\n", ++ priv->ndev->name); ++ goto fail; ++ } ++ ++ e = create_proc_entry("scan_age", S_IFREG | S_IRUGO | S_IWUSR, ++ priv->dir_dev); ++ if (e) { ++ e->read_proc = proc_get_scan_age; ++ e->write_proc = proc_set_scan_age; ++ e->data = priv->ndev; ++ } else { ++ printk(KERN_ERR ++ "Unable to initialize " ++ "/proc/net/ipw2100/%s/scan_age\n", ++ priv->ndev->name); ++ goto fail; ++ } ++ ++ e = create_proc_entry("fatal_error", S_IFREG | S_IRUGO | S_IWUSR, ++ priv->dir_dev); ++ if (e) { ++ e->read_proc = proc_get_fatal_error; ++ e->write_proc = proc_set_fatal_error; ++ e->data = priv->ndev; ++ } else { ++ printk(KERN_ERR ++ "Unable to initialize " ++ "/proc/net/ipw2100/%s/fatal_error\n", ++ priv->ndev->name); ++ goto fail; ++ } ++ ++ e = create_proc_entry("state", S_IFREG | S_IRUGO | S_IWUSR, ++ priv->dir_dev); ++ if (e) { ++ e->read_proc = proc_get_state; ++ e->write_proc = proc_set_state; ++ e->data = priv->ndev; ++ } else { ++ printk(KERN_ERR ++ "Unable to initialize " ++ "/proc/net/ipw2100/%s/state\n", ++ priv->ndev->name); ++ goto fail; ++ } ++ ++ IPW_DEBUG_INFO("exit %s\n", priv->ndev->name); ++ ++ return 0; ++ ++ fail: ++ ipw2100_proc_dev_cleanup(priv); ++ IPW_DEBUG_INFO("exit on fail %s\n", priv->ndev->name); ++ ++ return -ENOMEM; ++} ++ ++void ipw2100_proc_dev_cleanup(struct ipw2100_priv *priv) ++{ ++ IPW_DEBUG_INFO("enter %s\n", priv->ndev->name); ++ ++ if (priv->dir_dev) { ++ remove_proc_entry("stats", priv->dir_dev); ++ remove_proc_entry("internals", priv->dir_dev); ++ remove_proc_entry("txqueue", priv->dir_dev); ++ remove_proc_entry("rxqueue", priv->dir_dev); ++ remove_proc_entry("cardmem", priv->dir_dev); ++ remove_proc_entry("scan_age", priv->dir_dev); ++ remove_proc_entry("bssinfo", priv->dir_dev); ++ remove_proc_entry("state", priv->dir_dev); ++ remove_proc_entry("version", priv->dir_dev); ++ remove_proc_entry("hw", priv->dir_dev); ++ remove_proc_entry("registers", priv->dir_dev); ++ remove_proc_entry("memory", priv->dir_dev); ++ remove_proc_entry("ordinals", priv->dir_dev); ++ remove_proc_entry("pci", priv->dir_dev); ++ remove_proc_entry("fatal_error", priv->dir_dev); ++ remove_proc_entry(priv->ndev->name, ipw2100_proc); ++ priv->dir_dev = NULL; ++ } ++ ++ IPW_DEBUG_INFO("exit %s\n", priv->ndev->name); ++} ++ ++ ++/** ++ * Initialize ipw2100 proc filesystem's entry. ++ * ++ * @returns 0 if ok, < 0 errno code on error [-ENOMEM]. ++ * ++ * On error, it takes care of cleaning up as if nothing had been ++ * done. ++ */ ++static ++int ipw2100_proc_init(void) ++{ ++ struct proc_dir_entry *e; ++ ++ IPW_DEBUG_INFO("enter\n"); ++ ++ ipw2100_proc = create_proc_entry(DRV_NAME, S_IFDIR, proc_net); ++ if (ipw2100_proc == NULL) ++ goto fail_ipw2100; ++ ++ /* Next we create only if we compiled in debug support */ ++ if (!IPW_DEBUG_ENABLED) ++ goto skip_debug; ++ ++ e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR, ++ ipw2100_proc); ++ if (e == NULL) ++ goto fail_debug; ++ e->read_proc = proc_get_debug_level; ++ e->write_proc = proc_set_debug_level; ++ e->data = NULL; ++ ++skip_debug: ++ IPW_DEBUG_INFO("exit\n"); ++ return 0; ++ ++fail_debug: ++ printk(KERN_ERR DRV_NAME ": Unable to initialize " ++ "/proc/net/" DRV_NAME "/debug_level\n"); ++ remove_proc_entry(DRV_NAME, proc_net); ++ ipw2100_proc = NULL; ++ goto fail; ++ ++fail_ipw2100: ++ printk(KERN_ERR DRV_NAME ": Unable to initialize /proc/net/" ++ DRV_NAME "\n"); ++ ++fail: ++ IPW_DEBUG_INFO("exit on fail\n"); ++ return -ENOMEM; ++} ++ ++ ++/** ++ * Releases /proc filesystem entries. ++ * ++ * Assumes all went ok when allocating them. ++ */ ++static void ipw2100_proc_cleanup(void) ++{ ++ IPW_DEBUG_INFO("enter\n"); ++ ++ if (IPW_DEBUG_ENABLED && ipw2100_proc) ++ remove_proc_entry("debug_level", ipw2100_proc); ++ remove_proc_entry(DRV_NAME, proc_net); ++ IPW_DEBUG_INFO("exit\n"); ++} + + + static int status_queue_allocate(struct ipw2100_priv *priv, int entries) +@@ -6647,8 +7064,17 @@ static int ipw2100_pci_init_one(struct p + + printk(KERN_INFO "%s: Bound to %s\n", dev->name, pci_name(pdev)); + +- /* perform this after register_netdev so that dev->name is set */ +- sysfs_create_group(&pdev->dev.kobj, &ipw2100_attribute_group); ++ /* perform this after register_netdev so that dev->name is ++ * set */ ++ err = ipw2100_proc_dev_init(priv); ++ if (err) { ++ printk(KERN_ERR ++ "%s: Failed to create /proc node\n", ++ dev->name); ++ err = -EIO; ++ goto fail; ++ } ++ + netif_carrier_off(dev); + + /* If the RF Kill switch is disabled, go ahead and complete the +@@ -6698,7 +7124,7 @@ static int ipw2100_pci_init_one(struct p + + /* These are safe to call even if they weren't allocated */ + ipw2100_queues_free(priv); +- sysfs_remove_group(&pdev->dev.kobj, &ipw2100_attribute_group); ++ ipw2100_proc_dev_cleanup(priv); + + free_netdev(dev); + pci_set_drvdata(pdev, NULL); +@@ -6720,7 +7146,7 @@ static void __devexit ipw2100_pci_remove + + if (priv) { + dev = priv->ndev; +- sysfs_remove_group(&pdev->dev.kobj, &ipw2100_attribute_group); ++ ipw2100_proc_dev_cleanup(priv); + + #ifdef CONFIG_PM + if (ipw2100_firmware.version) +@@ -6912,17 +7338,16 @@ static int __init ipw2100_init(void) + printk(KERN_INFO DRV_NAME ": Compiled with LEGACY FW load.\n"); + #endif + +- ret = pci_module_init(&ipw2100_pci_driver); +- + /* If debug module parameter declared, set debug_level to that */ + if (debug != -1) + ipw2100_debug_level = debug; + +-#ifdef CONFIG_IPW_DEBUG +- driver_create_file(&ipw2100_pci_driver.driver, +- &driver_attr_debug_level); +-#endif +- ++ ret = ipw2100_proc_init(); ++ if (!ret) { ++ ret = pci_module_init(&ipw2100_pci_driver); ++ if (ret) ++ ipw2100_proc_cleanup(); ++ } + return ret; + } + +@@ -6933,11 +7358,8 @@ static int __init ipw2100_init(void) + static void __exit ipw2100_exit(void) + { + /* FIXME: IPG: check that we have no instances of the devices open */ +-#ifdef CONFIG_IPW_DEBUG +- driver_remove_file(&ipw2100_pci_driver.driver, +- &driver_attr_debug_level); +-#endif + pci_unregister_driver(&ipw2100_pci_driver); ++ ipw2100_proc_cleanup(); + } + + module_init(ipw2100_init); diff --git a/package/avm/ipw2100/ipw2100-modparam-perm.patch b/package/avm/ipw2100/ipw2100-modparam-perm.patch new file mode 100644 index 000000000..38501ea0f --- /dev/null +++ b/package/avm/ipw2100/ipw2100-modparam-perm.patch @@ -0,0 +1,22 @@ +diff -urp ipw2100-0.55/ipw2100.c ipw2100-0.55-modparam/ipw2100.c +--- ipw2100-0.55/ipw2100.c 2004-09-28 01:29:17.000000000 +0800 ++++ ipw2100-0.55-modparam/ipw2100.c 2004-09-28 13:07:17.989689056 +0800 +@@ -250,12 +250,12 @@ MODULE_PARM(disable, "i"); + #else /* LINUX_VERSION_CODE < 2.6.0 */ + + #include +-module_param(debug, int, -1); +-module_param(if_name, charp, 0); +-module_param(mode, int, 0); +-module_param(channel, int, 1); +-module_param(associate, int, 1); +-module_param(disable, int, 1); ++module_param(debug, int, 0444); ++module_param(if_name, charp, 0444); ++module_param(mode, int, 0444); ++module_param(channel, int, 0444); ++module_param(associate, int, 0444); ++module_param(disable, int, 0444); + + #endif /* LINUX_VERSION_CODE < 2.6.0 */ + diff --git a/package/avm/ipw2100/ipw2100.desc b/package/avm/ipw2100/ipw2100.desc index 56a71ff8b..a6fb5b31b 100644 --- a/package/avm/ipw2100/ipw2100.desc +++ b/package/avm/ipw2100/ipw2100.desc @@ -37,8 +37,8 @@ [L] GPL [S] Beta -[V] 0.54 +[V] 0.55 [P] X -?---5---9 800.000 -[D] 379498497 ipw2100-0.54.tgz http://dl.sourceforge.net/ipw2100/ +[D] 3903702856 ipw2100-0.55.tgz http://dl.sourceforge.net/ipw2100/ diff --git a/package/avm/ipw2100/rf_disable.2.patch b/package/avm/ipw2100/rf_disable.2.patch new file mode 100644 index 000000000..dfcdc1edd --- /dev/null +++ b/package/avm/ipw2100/rf_disable.2.patch @@ -0,0 +1,69 @@ +diff -urp ipw2100-0.54/ipw2100.c ipw2100-0.54-new/ipw2100_main.c +--- ipw2100-0.54/ipw2100.c 2004-09-01 04:23:09.000000000 +0800 ++++ ipw2100-0.54-new/ipw2100_main.c 2004-09-14 13:26:20.742098168 +0800 +@@ -1373,6 +1373,13 @@ static int ipw2100_up(struct ipw2100_pri + u32 lock; + u32 ord_len = sizeof(lock); + ++ /* Quite if manually disabled. */ ++ if (priv->manual_disable) { ++ printk(KERN_INFO "%s: Radio is disabled by Manual Disable " ++ "switch\n", priv->ndev->name); ++ return 0; ++ } ++ + /* If the interrupt is enabled, turn it off... */ + spin_lock_irqsave(&priv->low_lock, flags); + ipw2100_hw_disable_interrupt(priv); +@@ -1419,26 +1426,17 @@ static int ipw2100_up(struct ipw2100_pri + } + + priv->in_scan = 0; ++ priv->rf_kill = ipw2100_get_rf_switch(priv); + +- if (priv->hw_features & HW_FEATURE_RFKILL) +- priv->rf_kill = ipw2100_get_rf_switch(priv); +- else +- priv->rf_kill = 0; +- +- if (priv->rf_kill || priv->manual_disable) { +- if (priv->rf_kill) +- printk(KERN_INFO "%s: Radio is disabled by RF switch\n", +- priv->ndev->name); +- if (priv->manual_disable) +- printk(KERN_INFO "%s: Radio is disabled by Manual Disable switch\n", +- priv->ndev->name); ++ if (priv->rf_kill) { ++ printk(KERN_INFO "%s: Radio is disabled by RF switch\n", ++ priv->ndev->name); + + if (priv->stop_rf_check) { + priv->stop_rf_check = 0; + priv->rf_switch_timer.expires = jiffies + HZ; + add_timer(&priv->rf_switch_timer); + } +- + /* Since the RF switch is off, we will defer + * the sending of the HOST_COMPLETE */ + deferred = 1; +@@ -5869,7 +5867,7 @@ static void shim__set_security(struct ie + priv->sec.flags & BIT(0) ? '1' : '0'); + + if (!priv->connected) +- ipw2100_configure_security(priv, 0); ++ ipw2100_configure_security(priv, priv->manual_disable); + } + + static struct ieee80211_helper_functions ipw2100_ieee_callbacks = { +@@ -6219,7 +6217,10 @@ static void ipw2100_rf_switch_check(unsi + if (!priv->rf_kill) { + /* Kill timer; we don't need to poll for RF going + * off since the firmware will tell us */ +- priv->stop_rf_check = 1; ++ if (!priv->stop_rf_check) { ++ priv->stop_rf_check = 1; ++ del_timer_sync(&priv->rf_switch_timer); ++ } + + /* Restart the NIC */ + schedule_reset(priv); diff --git a/package/avm/ipw2100/stop-adapter.patch b/package/avm/ipw2100/stop-adapter.patch new file mode 100644 index 000000000..4d5c25c24 --- /dev/null +++ b/package/avm/ipw2100/stop-adapter.patch @@ -0,0 +1,14 @@ +diff -urp ipw2100-0.54/ipw2100.c ipw2100-0.54-test/ipw2100_main.c +--- ipw2100-0.54/ipw2100.c 2004-09-15 13:11:28.000000000 +0800 ++++ ipw2100-0.54-test/ipw2100_main.c 2004-09-16 10:17:51.166570568 +0800 +@@ -6567,6 +6567,10 @@ static int ipw2100_pci_init_one(struct p + printk(KERN_ERR + "%s: failed in call to enable adapter.\n", + priv->ndev->name); ++ if (ipw2100_hw_stop_adapter(priv)) ++ printk(KERN_ERR "%s: Error stopping adapter.\n", ++ priv->ndev->name); ++ + err = -EIO; + goto fail; + }